Ë
    tPêj’ˆ  ã                  ó�  — U d dl mZ d dlZd dlZd dlZd dlZd dlmZmZ d dl	m
Z
mZmZmZmZmZ d dlZd dlmZ d dlmZ d dl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m Z m!Z! d dl"m#Z#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/m0Z0 d dl1m2Z2m3Z3m4Z4 d dl5m6Z6m7Z7 e
rd dl8m9Z: d dl;m<Z< dZ=de>d<   dZ?de>d<    ej€                  d«      ZAde>d<   dZBde>d<   d0d„ZCd1d„ZDd2d„ZE	 	 	 	 	 	 d3d „ZFd4d!„ZG	 	 	 	 	 	 	 	 d5d"„ZHd6d#„ZId7d$„ZJd8d%„ZKd9d&„ZLd:d'„ZMd;d(„ZN	 	 	 	 	 	 d<d)„ZOd=d*„ZPd=d+„ZQ	 	 	 	 	 	 d>d,„ZR	 	 	 	 	 	 d>d-„ZS G d.„ d/e«      ZTy)?é    )ÚannotationsN)ÚMappingÚSequence)ÚTYPE_CHECKINGÚAnyÚClassVarÚFinalÚLiteralÚ	TypeGuard)ÚHTTPException)ÚResponse)Úverbose_proxy_logger)Úget_protected_indices)ÚCustomGuardrailÚlog_guardrail_information)Úget_attribute_or_keyÚget_tool_calls_from_responseÚgroup_tool_exchangesÚhas_tool_with_name)Úget_async_httpx_clientÚhttpxSpecialProvider)Úassistant_text_from_responseÚcontent_to_textÚis_all_text_partsÚmerge_rewritten_text_parts)ÚHEADROOM_GUARDRAIL_PROVIDER)Úget_secret_str)ÚGuardrailEventHooksÚMode)ÚHEADROOM_CONVERTED_STREAM_KEYÚAgenticLoopPlanÚAgenticLoopRequestPatch)Ú	CallTypesÚGenericGuardrailAPIInputs)ÚLogging)ÚGuardrailConfigModelzx-headroom-bypassr	   ÚBYPASS_HEADERÚheadroom_retrieveÚHEADROOM_RETRIEVE_TOOL_NAMEzhash=([a-f0-9]{24})Ú_HASH_PATTERNi„  Ú_HASH_CACHE_TTL_SECONDSc                ó"   — t        | t        «      S ©N)Ú
isinstanceÚdict©Úvalues    ú/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/guardrails/guardrail_hooks/headroom/headroom.pyÚ_is_str_object_dictr3   9   ó   € Ü�eœTÓ"Ð"ó    c                ó"   — t        | t        «      S r-   )r.   Úlistr0   s    r2   Ú_is_object_listr8   =   r4   r5   c                ó¼   — g }| D ]T  }|j                  d«      }t        |«      r%t        |«      }|r|j                  i |¥d|i¥«       ŒD|j                  |«       ŒV |S )aL  Collapse all-text list-of-parts content to plain strings for /v1/compress.

    The compression service's transforms only rewrite string content and skip
    the OpenAI list-of-parts shape, which is what every Anthropic-format
    request translates to. Only rows whose parts are ALL text are flattened:
    cache_control breakpoints are positional (each caches the prefix ending
    at its part), so merging text across a non-text part would move a later
    breakpoint to the other side of it. Rows with non-text parts are sent
    unchanged and pass through the service untouched.
    Úcontent)Úgetr   r   Úappend)ÚmessagesÚ	flattenedÚmsgr:   Útexts        r2   Ú!_flatten_messages_for_compressionrA   A   so   € ð 13€IØò ˆØ—'‘'˜)Ó$ˆÜ˜WÔ%Ü" 7Ó+ˆDÙØ× Ñ Ð!9 CÐ!9¨°DÑ!9Ô:ØØ×Ñ˜Õðð Ðr5   c           	     ó  — t        |«      t        | «      k7  r|S t        | |«      D ],  \  }}|j                  d«      |j                  d«      k7  sŒ*|c S  g }t        | |«      D ]   \  }}|j                  d«      }|j                  d«      }t        |t        «      rXt        |t
        «      rH|t        |«      k(  r|j                  i |¥d|i¥«       Œn|j                  i |¥dt        ||«      i¥«       Œ�|j                  |«       Œ¢ |S )aL  Write compressed text back into each original row's content shape.

    Rows are matched positionally; the pairing is only trusted when the
    service kept the row count and every role lines up. If it restructured
    the conversation (e.g. dropped rows), its output is adopted as-is, which
    is the pre-flattening behavior.
    Úroler:   )	ÚlenÚzipr;   r.   r7   Ústrr   r<   r   )Ú	originalsÚreturnedÚorigÚretÚrestoredÚorig_contentÚret_contents          r2   Ú_restore_content_shapesrN   X   sþ   € ô ˆ8ƒ}œ˜I›Ò&ØˆÜ˜ HÓ-ò ‰	ˆˆcØ�8‰8�FÓ˜sŸw™w v›Ó.ØŠOðð 02€HÜ˜ HÓ-ò !‰	ˆˆcØ—x‘x 	Ó*ˆØ—g‘g˜iÓ(ˆÜ�l¤DÔ)¬j¸ÄcÔ.JØœo¨lÓ;Ò;ð —‘Ð @ 3Ð @¨	°<Ñ @ÕAà—‘Ð i 3Ð i¨	Ô3MÈlÐ\gÓ3hÑ iÕjà�O‰O˜CÕ ð!ð €Or5   c                ól   ‡— t        t        | «      «      Š‰t        ˆfd„t        | «      D «       «      z  S )a–  Indices headroom must not send to the compression service.

    ``get_protected_indices`` is litellm's own compression policy: the system
    rows, the last user row, the last assistant row. It is expanded over whole
    tool exchanges the way ``compress()`` expands it, so a protected assistant
    tool call cannot end up answered by a marker standing in for the result the
    model just asked for.
    c              3  óX   •K  — | ]!  }t        ˆfd „|D «       «      r|D ]  }|–— Œ Œ# y­w)c              3  ó&   •K  — | ]  }|‰v –— Œ
 y ­wr-   © )Ú.0ÚmemberÚ	protecteds     €r2   ú	<genexpr>z/_protected_indices.<locals>.<genexpr>.<genexpr>„   s   øè ø€ Ò7 vˆv˜Ô"Ñ7ùs   ƒN)Úany)rS   ÚgroupÚindexrU   s      €r2   rV   z%_protected_indices.<locals>.<genexpr>�   s<   øè ø€ ò !àÜÓ7°Ô7Ô7Øò	!ð ô 	ð!Øñ!ùs   ƒ'*)Ú	frozensetr   r   )r=   rU   s    @r2   Ú_protected_indicesr[   w   s;   ø€ ô !Ô!6°xÓ!@ÓA€IØ”yó !ä)¨(Ó3ô!ó ñ ð r5   c                óà   ‡— t        ˆfd„t        t        | «      «      D «       «      }t        t	        ||«      «      }t        t        | «      «      D �cg c]  }|‰v r| |   n||   ‘Œ c}S c c}w )a2  Put the rows that were held back from compression at their original positions.

    Requires one returned row per row actually sent, which ``_call_compress``
    enforces; a service that changed the row count is treated as a failure
    there, because a reshaped conversation cannot be re-interleaved.
    c              3  ó,   •K  — | ]  }|‰vsŒ|–— Œ y ­wr-   rR   )rS   rY   Úprotected_indicess     €r2   rV   z._restore_protected_messages.<locals>.<genexpr>”   s   øè ø€ Ò!l¨EÈUÐZkÒMk¤%Ñ!lùs   ƒ	�)ÚtupleÚrangerD   r/   rE   )r=   Ú
compressedr^   Úsent_positionsÚcompressed_by_indexrY   s     `   r2   Ú_restore_protected_messagesrd   ‰   sp   ø€ ô "Ó!l´U¼3¸x»=Ó5IÔ!lÓl€NÜ!%¤c¨.¸*Ó&EÓ!FÐächÔilÐmuÓivÓcwöØZ_˜5Ð$5Ñ5ˆ�ŠÐ;NÈuÑ;UÑUòð ùò s   ÁA+c                ó"   — | dk(  r| |ddœS | |dœS )zÀBuild error details for failed /v1/compress responses.

    Adds troubleshooting hints for known deployment-related errors while
    preserving the upstream status code and response body.
    é”  a-  The Headroom compression endpoint returned HTTP 404. Verify that the configured Headroom endpoint is correct and that the compression endpoint is available. If you are using a self-hosted deployment, some deployments require enabling remote compression (for example, HEADROOM_COMPRESS_ALLOW_REMOTE=1).)Ústatus_codeÚbodyÚhint©rg   rh   rR   rj   s     r2   Ú_build_compress_failure_detailrk   ›   s/   € ð �cÒà&ØðOñ	

ð 
	
ð '°Ñ5Ð5r5   c                ó‚  — g }| D ]·  }|j                  d«      }t        |t        «      r%|j                  t        j                  |«      «       ŒIt        |t        «      sŒZ|D ]Y  }t        |t        «      sŒ|j                  d«      }t        |t        «      sŒ6|j                  t        j                  |«      «       Œ[ Œ¹ |S )Nr:   r@   )r;   r.   rF   Úextendr*   Úfindallr7   r/   )r=   Úhashesr?   r:   Úblockr@   s         r2   Úextract_hashes_from_messagesrq   °   s¢   € Ø!€FØò 	CˆØ—'‘'˜)Ó$ˆÜ�gœsÔ#Ø�M‰Mœ-×/Ñ/°Ó8Õ9Ü˜¤Õ&Ø ò C�Ü˜e¤TÕ*Ø Ÿ9™9 VÓ,�DÜ! $¬Õ,ØŸ™¤m×&;Ñ&;¸DÓ&AÕBñ	Cð	Cð €Mr5   c                 ó8   — dt         dddddœdddœdœd	gd
œdœdœS )NÚfunctionzRetrieve original content that was compressed by Headroom. Call this when you encounter a compression marker containing a hash.ÚobjectÚstringz6The 24-character hex hash from the compression marker.)ÚtypeÚdescriptionz0Optional search query for BM25-ranked retrieval.)ÚhashÚqueryrx   )rv   Ú
propertiesÚrequired)Únamerw   Ú
parameters)rv   rs   )r)   rR   r5   r2   Ú_build_headroom_retrieve_toolr~   ¿   sM   € àä/ðWð !ð !)Ø'_ñð
 !)Ø'Yññ	ð $˜Hññ
ñð r5   c                óŽ   — t        | dd«      }t        |t        «      r|r|S |j                  d«      }t        |t        «      r|S dS )zÛResolve the litellm_call_id shared by a request's pre-call hook and its
    agentic-loop hooks, so CCR hash validation can be scoped per call instead
    of trusting any hash-shaped string that shows up in message text.Úlitellm_call_idN)Úgetattrr.   rF   r;   )Úlogging_objÚrequest_stateÚlogging_call_idÚkwargs_call_ids       r2   Ú_resolve_call_idr†   Ú   sJ   € ô % [Ð2CÀTÓJ€OÜ�/¤3Ô'©OØÐØ)×-Ñ-Ð.?Ó@€NÜ'¨¼Ô<ˆ>ÐFÀ$ÐFr5   c                ó"   — t        | t        «      S r-   )r   r)   )Útoolss    r2   Úhas_headroom_retrieve_toolr‰   å   s   € Ü˜eÔ%@ÓAÐAr5   c                ór   — t        | «      D �cg c]  }|d   t        k(  r|d   d|d   |d   dœ‘Œ  c}S c c}w )Nr|   Úidrs   Ú	arguments)r‹   rv   r|   rŒ   )r   r)   )ÚresponseÚtcs     r2   Ú_extract_headroom_tool_callsr�   é   sL   € ô /¨xÓ8öàØˆf‰:Ô4Ò4ð �$‰x °R¸±ZÈbÐQ\ÉoÓ^òð ùò s   Ž#4c                óâ   — dt        | «      |D ��cg c]O  \  }}|j                  d«      d|j                  d«      t        j                  |j                  di «      «      dœdœ‘ŒQ c}}dœS c c}}w )	a´  Rebuild the chat-completions assistant turn for the retrieval follow-up.

    Only the ``headroom_retrieve`` calls are echoed, each answered by a tool
    result below. Other tool calls made in the same turn are omitted on purpose:
    the follow-up re-runs the model with the recovered content so it re-plans
    them. Echoing them would leave tool_calls with no matching tool result and
    the provider would reject the request.
    Ú	assistantr‹   rs   r|   rŒ   )r|   rŒ   )r‹   rv   rs   )rC   r:   Ú
tool_calls)r   r;   ÚjsonÚdumps)r�   Ú	retrievedÚ	tool_callÚ_s       r2   Ú&_build_assistant_message_from_responser˜   ñ   su   € ð Ü/°Ó9ð !*÷

ñ �	˜1ð  —m‘m DÓ)Ø"à%ŸM™M¨&Ó1Ü!%§¡¨I¯M©M¸+ÀrÓ,JÓ!Kñóó

ñð ùó

s   ‘AA+
c                ó8   — t        t        | dd «      t        «      S )NÚoutput©r.   r   r7   ©r�   s    r2   Ú_is_responses_api_responser�     s   € ô Ô*¨8°X¸tÓDÄdÓKÐKr5   c                ó8   — t        t        | dd «      t        «      S )Nr:   r›   rœ   s    r2   Ú_is_anthropic_messages_responserŸ     s   € ÜÔ*¨8°YÀÓEÄtÓLÐLr5   c                ó:  — t        | «      }d|rd|dœgng |D ��cg c]:  \  }}d|j                  d«      |j                  d«      |j                  di «      dœ‘Œ< c}}z   d	œ}d
|D ��cg c]  \  }}d|j                  d«      |dœ‘Œ c}}d	œ}||gS c c}}w c c}}w )a¨  Build Anthropic Messages API follow-up messages for a tool round-trip.

    Anthropic requires the tool_use block to be echoed back in an assistant
    message, paired with a tool_result block in a user message keyed by the
    same tool_use_id -- it does not accept chat-style tool-role messages. Any
    text the model wrote alongside the tool call is preserved, so its reasoning
    survives into the follow-up turn.
    r‘   r@   )rv   r@   Útool_user‹   r|   rŒ   )rv   r‹   r|   Úinput©rC   r:   ÚuserÚtool_result)rv   Útool_use_idr:   )r   r;   )r�   r•   r@   r–   r—   Úassistant_messager:   Úuser_messages           r2   Ú"_build_anthropic_followup_messagesr©     sÆ   € ô /¨xÓ8€DàÙ8<˜f¨dÑ3Ñ4À"ð !*÷
ñ �	˜1ð #Ø—m‘m DÓ)Ø!Ÿ™ fÓ-Ø"Ÿ™ {°BÓ7ó	ó
ñ	
ñ3Ðð ð '0÷
á"�	˜7ð #°9·=±=ÀÓ3FÐSZÓ[ó
ñ.€Lð ˜|Ð,Ð,ùó#
ùó
s   ›?B
Á(Bc                ó   — t        | «      }|rd|dœgng }|D ]s  \  }}|j                  d«      }|j                  d||j                  d«      t        j                  |j                  di «      «      dœ«       |j                  d||d	œ«       Œu |S )
aZ  Build Responses API input items for a tool round-trip.

    The Responses API does not accept chat-style assistant/tool messages as
    follow-up input; it requires the model's function_call to be echoed back
    paired with a function_call_output keyed by the same call_id. Any text the
    model wrote alongside the tool call is preserved.
    r‘   r£   r‹   Úfunction_callr|   rŒ   )rv   Úcall_idr|   rŒ   Úfunction_call_output)rv   r¬   rš   )r   r;   r<   r“   r”   )r�   r•   r@   Úitemsr–   r:   r¬   s          r2   Ú_build_responses_followup_itemsr¯   =  sœ   € ô /¨xÓ8€DÙX\°kÈdÑ-SÑ,TÐbd€EØ'ò 
^Ñˆ	�7Ø—-‘- Ó%ˆØ�‰à'Ø"Ø!Ÿ™ fÓ-Ü!ŸZ™Z¨	¯©°kÀ2Ó(FÓGñ	ô	
ð 	�‰Ð4ÀÐT[Ñ\Õ]ð
^ð €Lr5   c                  ó€  ‡ — e Zd ZU dZded<    eeh«      Zded<   edd„«       Z		 	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 dˆ fd„Z
dd„Zdd	„Zdd
„Z	 	 	 	 	 	 	 	 dd„Z	 	 	 	 	 	 dd„Zddd„Ze	 d	 	 	 	 	 	 	 	 	 dd„«       Z	 	 	 	 	 	 dˆ fd„Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d d„Zed!d„«       Zˆ xZS )"ÚHeadroomGuardrailTzClassVar[bool]Ú!records_own_guardrail_informationzClassVar[frozenset[str]]Úserver_fulfilled_tool_namesc                óB   — t         j                  t         j                  gS r-   )r   Úpre_callÚ	post_call)Úclss    r2   Úget_supported_event_hooksz+HeadroomGuardrail.get_supported_event_hooks\  s    € ô  ×(Ñ(Ü×)Ñ)ð
ð 	
r5   c           	     ót  •— |xs t        d«      xs dj                  d«      | _        | j                  st        d«      ‚|xs t        d«      | _        || _        |dk(  rdnd| _        t        t        j                  ¬«      | _
        i | _        t        ‰| �5  |||t        | j                  «       «      ¬	«       y )
NÚHEADROOM_API_BASEÚ ú/zqHeadroom guardrail requires an API base URL. Set `api_base` in the guardrail config or HEADROOM_API_BASE env var.ÚHEADROOM_API_KEYÚ	fail_openÚfail_closed)Úllm_provider)Úguardrail_nameÚ
event_hookÚ
default_onÚsupported_event_hooks)r   ÚrstripÚheadroom_api_baseÚ
ValueErrorÚheadroom_api_keyÚheadroom_modelÚunreachable_fallbackr   r   ÚGuardrailCallbackÚasync_handlerÚ_issued_hashes_by_call_idÚsuperÚ__init__r7   r¸   )	ÚselfÚapi_baseÚapi_keyÚmodelrÁ   rÂ   rÃ   rÊ   Ú	__class__s	           €r2   rÏ   zHeadroomGuardrail.__init__c  sÇ   ø€ ð #+Ò"W¬nÐ=PÓ.QÒ"WÐUW×!_Ñ!_Ð`cÓ!dˆÔØ×%Ò%ÜðWóð ð !(Ò M¬>Ð:LÓ+MˆÔØ#ˆÔà/°;Ò>‰KÀMð 	Ô!ô 4Ü-×?Ñ?ô
ˆÔð SUˆÔ&Ü‰ÑØ)Ø!Ø!Ü"& t×'EÑ'EÓ'GÓ"Hð	 	õ 	
r5   c                óØ   — |j                  d«      }t        |«      sy|j                  d«      }t        |«      sy|j                  t        «      }t        |«      j	                  «       dk(  S )NÚproxy_server_requestFÚheadersÚtrue)r;   r3   r'   rF   Úlower)rÐ   Úrequest_dataÚpsrr×   r1   s        r2   Ú_should_bypassz HeadroomGuardrail._should_bypassƒ  s]   € Ø!×%Ñ%Ð&<Ó=ˆÜ" 3Ô'ØØŸ™ Ó+ˆÜ" 7Ô+ØØ—{‘{¤=Ó1ˆÜ�5‹z×ÑÓ! VÑ+Ð+r5   c                óJ   — ddi}| j                   rd| j                   › �|d<   |S )NzContent-Typezapplication/jsonzBearer ÚAuthorization)rÈ   )rÐ   r×   s     r2   Ú_request_headersz"HeadroomGuardrail._request_headers�  s3   € Ø*8Ð:LÐ)MˆØ× Ò Ø)0°×1FÑ1FÐ0GÐ'HˆG�OÑ$Øˆr5   c                ó¸   — t        j                  «       }| j                  j                  «       D ���ci c]  \  }\  }}||kD  r|||f“Œ c}}}| _        y c c}}}w r-   )ÚtimeÚ	monotonicrÍ   r®   )rÐ   Únowr¬   ro   Úexpirys        r2   Ú_prune_expired_hashesz'HeadroomGuardrail._prune_expired_hashes“  s^   € Ü—^‘^Ó%ˆð .2×-KÑ-K×-QÑ-QÓ-S÷*
ð *
á)�Ñ)˜& &Ø˜Š|ð �f˜fÐ%Ñ%ô*
ˆÕ&ùô *
s   ³Ac                ót   — | j                   dk(  rt        j                  d||«       |S t        dd|i|¥¬«      ‚)Nr¾   zNHeadroom: %s; fail_open configured, forwarding request uncompressed. detail=%siö  Úerror)rg   Údetail)rÊ   r   Úcriticalr   )rÐ   r=   rç   rè   s       r2   Ú_handle_compress_failurez*HeadroomGuardrail._handle_compress_failure›  sG   € ð ×$Ñ$¨Ò3Ü ×)Ñ)Ø`ØØôð
 ˆOÜ¨°W¸eÐ4NÀvÐ4NÔOÐOr5   c           	   ƒ  ó@  K  — d|i}|r||d<   	 | j                   j                  | j                  › d�|| j                  «       ¬«      ƒ d {  –—† }|€| j                  |d	i «      di fS |}|j                  d
k7  r4| j                  |dt        |j                  |j                  «      «      di fS 	 |j#                  «       }t'        |«      s%| j                  |dd|j                  d d i«      di fS |j)                  d«      }t+        |«      s"| j                  |dd|j                  i«      di fS |D �	cg c]  }	t'        |	«      sŒ|	‘Œ }
}	|
s"| j                  |dd|j                  i«      di fS t-        |
«      t-        |«      k7  r+| j                  |dt-        |«      t-        |
«      dœ«      di fS t/        j0                  d|j)                  dd«      |j)                  dd«      |j)                  dd«      «       dD �ci c]  }||v r|||   “Œ }}|j)                  d«      }|j)                  d«      }d|vrTt3        |t4        t6        f«      r>t3        |t8        «      s.t3        |t4        t6        f«      rt3        |t8        «      s||z
  |d<   |
d|fS 7 �Œ@# t        j
                  $ rR}| j                  |dt        |j                  j                  |j                  j                  «      «      di fcY d }~S d }~wt        j                  t        j                  t        j                  t        j                  f$ r+}| j                  |ddt!        |«      i«      di fcY d }~S d }~ww xY w# t$        $ r( | j                  |dd|j                  d d i«      di fcY S w xY wc c}	w c c}w ­w)Nr=   rÓ   z/v1/compress)Úurlr“   r×   z.Headroom compression service returned an errorFz(Headroom compression service unreachablerè   z1Headroom compression service returned no responseéÈ   z7Headroom compression service returned non-JSON responserh   iô  z?Headroom compression service returned unexpected response shapez8Headroom compression service response missing 'messages'z8Headroom compression service returned empty message listz6Headroom compression service changed the message count)ÚsentrH   z8Headroom: compressed %s tokens -> %s tokens (ratio %.2f)Útokens_beforeú?Útokens_afterÚcompression_ratior   )rï   rñ   Útokens_savedrò   Útransforms_appliedró   T)rÌ   ÚpostrÆ   rß   ÚhttpxÚHTTPStatusErrorrê   rk   r�   rg   r@   ÚConnectErrorÚTimeoutExceptionÚTransportErrorÚlitellmÚTimeoutrF   r“   rÇ   r3   r;   r8   rD   r   Údebugr.   ÚintÚfloatÚbool)rÐ   r=   rÓ   ÚpayloadÚraw_responseÚer�   rh   Úcompressed_messagesÚitemÚfilteredÚkeyÚstatsrï   rñ   s                  r2   Ú_call_compressz HeadroomGuardrail._call_compressª  s  è ø€ ð
 .8¸Ð,BˆÙØ$ˆG�GÑð	Ø7;×7IÑ7I×7NÑ7NØ×-Ñ-Ð.¨lÐ;ØØ×-Ñ-Ó/ð 8Oó 8÷ 2ˆLð2 Ðà×-Ñ-ØØGØóð
 Øðð ð *6ˆà×Ñ 3Ò&à×-Ñ-ØØDÜ2°8×3GÑ3GÈÏÉÓWóð
 Øðð ð	Ø"*§-¡-£/ˆDô # 4Ô(à×-Ñ-ØØUØ˜XŸ]™]¨4¨CÐ0Ð1óð
 Øðð ð &*§X¡X¨jÓ%9ÐÜÐ2Ô3à×-Ñ-ØØNØ˜XŸ]™]Ð+óð
 Øðð ð -@Ö] DÔCVÐW[ÕC\š4Ð]ˆÐ]Ùà×-Ñ-ØØNØ˜XŸ]™]Ð+óð
 Øðð ô ˆx‹=œC ›MÒ)ð ×-Ñ-ØØLÜ  ›]¼¸H»ÑFóð
 Øðð ô 	×"Ñ"ØFØ�H‰H�_ cÓ*Ø�H‰H�^ SÓ)Ø�H‰HÐ(¨!Ó,ô		
ðö

àð �d‰{ð ��c‘‰Nð

ˆð 

ð  %Ÿy™y¨Ó9ˆØ#Ÿi™i¨Ó7ˆà %Ñ'Ü˜=¬3´¨,Ô7Ü˜}¬dÔ3Ü˜<¬#¬u¨Ô6Ü˜|¬TÔ2ð
 %2°LÑ$@ˆE�.Ñ!Ø˜˜uÐ$Ð$ðW2úô
 ×$Ñ$ò 		à×-Ñ-ØØDÜ2°1·:±:×3IÑ3IÈ1Ï:É:Ï?É?Ó[óð
 Øðõ ûô ×"Ñ"¤E×$:Ñ$:¼E×<PÑ<PÔRY×RaÑRaÐbò 		à×-Ñ-ØØ>Øœs 1›vÐ&óð
 Øðõ ûð		ûôF ò 		à×-Ñ-ØØMØ˜XŸ]™]¨4¨CÐ0Ð1óð
 Øðò ð		üòB ^ùò@

ùs¦   ‚N�<J ÁJÁJ ÁANÂ.M  Â>A2NÄ0NÅNÅB4NÇ9NÈ
BNÊJ ÊMÊ!AK.Ë(MË)NË.AMÌ2 MÍMÍNÍMÍNÍ .NÎNÎNÎNc              ƒ  óü  K  — i }|r||d<   	 | j                   j                  | j                  › d|› �|| j                  «       ¬«      ƒ d {  –—† }|�|j                  dk(  rd|› d	�S |j                  d
k7  r4t        j                  d|j                  |«       d|j                  › d|› d�S 	 |j                  «       }t!        |«      r#|j                  d«      }t#        |t$        «      r|S t%        |«      S 7 Œ¨# t        j
                  t        j                  t        j                  t        j                  f$ r'}t        j                  d||«       d|› d�cY d }~S d }~ww xY w# t        $ r |j                  cY S w xY w­w)Nry   z/v1/retrieve/)rì   Úparamsr×   z)Headroom: retrieve failed for hash=%s: %sz%[Headroom: retrieval failed for hash=ú]rf   ú[Headroom: hash=z not found or expired]rí   z*Headroom: retrieve returned %s for hash=%sz[Headroom: retrieval error z
 for hash=Úoriginal_content)rÌ   r;   rÆ   rß   rö   rø   rù   rú   rû   rü   r   Úwarningrg   r“   rÇ   r@   r3   r.   rF   )rÐ   Ú
hash_valuery   r  r  r  rh   r  s           r2   Ú_call_retrievez HeadroomGuardrail._call_retrieveA  s•  è ø€ Ø(*ˆÙØ#ˆF�7‰Oð	IØ7;×7IÑ7I×7MÑ7MØ×-Ñ-Ð.¨m¸J¸<ÐHØØ×-Ñ-Ó/ð 8Nó 8÷ 2ˆLð Ð <×#;Ñ#;¸sÒ#BØ% j \Ð1GÐHÐHà×#Ñ# sÒ*Ü ×(Ñ(Ø<Ø×(Ñ(Øôð
 1°×1IÑ1IÐ0JÈ*ÐU_ÐT`Ð`aÐbÐbð	%Ø".×"3Ñ"3Ó"5ˆDô ˜tÔ$Ø&*§h¡hÐ/AÓ&BÐÜÐ*¬CÔ0Ø'Ð'ä�4‹yÐð=2ùô
 ×"Ñ"¤E×$:Ñ$:¼E×<PÑ<PÔRY×RaÑRaÐbò 	IÜ ×(Ñ(Ð)TÐV`ÐbcÔdØ:¸:¸,ÀaÐHÕHûð	Iûô" ò 	%Ø×$Ñ$Ò$ð	%üsl   ‚
E<�>C6 ÁC4ÁC6 ÁAE<Â+E! Â;9E<Ã4C6 Ã6AEÄ7EÅEÅE<ÅEÅE<Å!E9Å6E<Å8E9Å9E<c           
   ƒ  ó|  K  — |dk7  r|S | j                  |«      rt        j                  dt        «       |S |j	                  d«      }t        |«      r|s|S |D �cg c]  }t        |«      sŒ|‘Œ }}|s|S t        |«      }t        |«      D �	�cg c]  \  }	}|	|vsŒ|‘Œ }
}	}|
s|S | j                  xs |j	                  d«      }t        j                  «       }| j                  t        |
«      t        |t        «      r|nd ¬«      ƒ d {  –—† \  }}}t        j                  «       }ddlm} |s7| j#                  dd	i|d
t$        ||||z
  ¬«        ||| j&                  ¬«       |S t)        |t+        |
|¬«      |¬«      }| j#                  ||dt$        ||||z
  ¬«        ||| j&                  ¬«       t-        |«      }|si |¥d|i¥S | j/                  «        t1        ||«      }|s"t        t3        j4                  «       «      }||d<   t7        |«      t        j8                  «       t:        z   f| j<                  |<   |j	                  d«      }t?        «       }t        |t@        «      rtC        |«      stA        |«      |gz   }n$|€|g}nt        |t@        «      rtA        |«      n|g}i |¥||dœ¥S c c}w c c}}	w 7 �Œ®­w)NÚrequestz-Headroom: %s header set; skipping compressionÚstructured_messagesrÓ   )r=   rÓ   r   )Ú*add_guardrail_to_applied_guardrails_headerrç   z@headroom compression unavailable; request forwarded uncompressedÚguardrail_failed_to_respond)Úguardrail_json_responserÚ   Úguardrail_statusÚguardrail_providerÚ
start_timeÚend_timeÚduration)rÚ   rÁ   )rG   rH   )r=   ra   r^   Úsuccessr€   rˆ   )r  rˆ   )"rÜ   r   rý   r'   r;   r8   r3   r[   Ú	enumeraterÉ   rá   r	  rA   r.   rF   Ú)litellm.proxy.common_utils.callback_utilsr  Ú:add_standard_logging_guardrail_information_to_request_datar   rÁ   rd   rN   rq   rå   r†   ÚuuidÚuuid4rZ   râ   r+   rÍ   r~   r7   r‰   )rÐ   ÚinputsrÚ   Ú
input_typer‚   r  Úmr=   r^   ÚiÚcompressiblerÓ   r  rH   Úcompression_succeededr  r  r  ra   ro   r¬   Úexisting_toolsÚretrieve_toolÚmerged_toolss                           r2   Úapply_guardrailz!HeadroomGuardrail.apply_guardrailg  sÚ  è ø€ ð ˜Ò"ØˆMà×Ñ˜|Ô,Ü ×&Ñ&Ð'VÔXeÔfØˆMà%+§Z¡ZÐ0EÓ%FÐÜÐ2Ô3Ñ;NØˆMà&9ÖT Ô=PÐQRÕ=Sš1ÐTˆÐTÙØˆMô $6°hÓ#?ÐÜ-6°xÓ-@×_¡T Q¨ÀAÐM^ÒD^šqÐ_ˆÑ_ÙØˆMà×*Ñ*ÒG¨l×.>Ñ.>¸wÓ.GˆÜ ŸI™I›Kˆ
Ø7;×7JÑ7JÜ6°|ÓDÜ% e¬SÔ1‘%°tð 8Kó 8
÷ 2
Ñ.ˆÐ'¨ô Ÿ)™)›+ˆõ	
ñ %Ø×KÑKØ)0Ð2tÐ(uØ)Ø!>Ü#>Ø%Ø!Ø! JÑ.ð Lô ñ 7ÀLÐae×atÑatÕuð
 ˆMä7ØÜ.¸ÐPXÔYØ/ô
ˆ
ð 	×GÑGØ$)Ø%Ø&Ü:Ø!ØØ 
Ñ*ð 	Hô 	
ñ 	3ÀÐ]a×]pÑ]pÕqä4°ZÓ@ˆÙØ@�fÐ@Ð3°ZÑ@Ð@à×"Ñ"Ô$Ü" ;°Ó=ˆÙÜœ$Ÿ*™*›,Ó'ˆGØ.5ˆLÐ*Ñ+Ü3<¸VÓ3DÄdÇnÁnÓFVÔYpÑFpÐ2qˆ×&Ñ& wÑ/à &§
¡
¨7Ó 3ˆÜ<Ó>ˆÜ�n¤dÔ+Ô4NÈ~Ô4^Ü)-¨nÓ)=ÀÀÑ)O‰LØÐ#Ø)˜?‰Lä3=¸nÌdÔ3Sœ4 Ô/ÐZgÐYhˆLàS�&ÐS°ÀlÒSÐSùòi Uùó `ð2
ûs8   ‚AJ<ÁJ.Á,J.Á0J<ÂJ3ÂJ3Â A+J<ÄJ9ÄF.J<c              ƒ  ó  •K  — t         ‰| �  ||«      ƒ d {  –—† }|�|n|}|t        j                  t        j                  fvr|S |j                  d«      s|S t        |j                  d«      «      s|S i |¥ddt        di¥S 7 Œk­w)NÚstreamrˆ   FT)rÎ   Úasync_pre_call_deployment_hookr#   Ú
completionÚacompletionr;   r‰   r    )rÐ   ÚkwargsÚ	call_typeÚbase_resultÚ	effectiverÔ   s        €r2   r/  z0HeadroomGuardrail.async_pre_call_deployment_hookÐ  s™   øè ø€ ô
 $)¡7Ñ#IÈ&ÐR[Ó#\×\ˆØ*5Ð*A™;Àvˆ	ØœY×1Ñ1´9×3HÑ3HÐIÑIØÐØ�}‰}˜XÔ&ØÐÜ)¨)¯-©-¸Ó*@ÔAØÐð
Øð
à�eÜ)¨4ñ
ð 	
ð ]ús   ƒB—B˜A,Bc              ƒ  óV   K  — t        |«      sdi fS t        |«      }|sdi fS dd|ifS ­w)NFTr’   )r‰   r�   )	rÐ   r�   rÓ   r=   rˆ   r.  Úcustom_llm_providerr2  r’   s	            r2   Úasync_should_run_agentic_loopz/HeadroomGuardrail.async_should_run_agentic_loopã  sA   è ø€ ô *¨%Ô0Ø˜"�9Ðä8¸ÓBˆ
ÙØ˜"�9Ðà�l JÐ/Ð/Ð/ùs   ‚')c
              ƒ  óÌ  K  — |j                  dg «      }
| j                  «        t        ||	«      }|r)| j                  j                  |t	        «       df«      d   n	t	        «       }g }|
D ]é  }|j                  di «      }t        |t        «      r|j                  dd«      nd}t        |t        «      r|j                  d«      nd }t        |«      |vrt        j                  d|«       d	|› d
�}n1| j                  t        |«      |rt        |«      nd ¬«      ƒ d {  –—† }t        j                  d|t        |«      «       |j                  ||f«       Œë t        |«      rt        |«      t!        ||«      z   }nit#        |«      rt        |«      t%        ||«      z   }nEt'        ||«      }|D ��cg c]  \  }}d|j                  d«      |dœ‘Œ }}}t        |«      |gz   |z   }|j                  d«      xs |	j                  d«      }|j)                  «       D ��ci c]  \  }}|dk7  sŒ||“Œ }}}|}|�Ct+        |di «      j                  di «      }|j                  d|«      }t        |t        «      r|r|}t-        dt/        |||||	j)                  «       D ��ci c]   \  }}|j1                  d«      rŒ|dk7  sŒ||“Œ" c}}¬«      ddi¬«      S 7 �Œ³c c}}w c c}}w c c}}w ­w)Nr’   g        r   rŒ   rx   r»   ry   zKHeadroom CCR: rejecting hash=%s not produced by current request compressionr  z) was not produced by the current request])r  ry   z*Headroom CCR: retrieved hash=%s (%d chars)Útoolr‹   )rC   Útool_call_idr:   Ú
max_tokensÚmodel_call_detailsÚagentic_loop_paramsrÓ   TÚ	_headroomÚlitellm_logging_obj)rÓ   r=   r<  Úoptional_paramsr2  Ú	tool_typeÚheadroom_ccr)Úrun_agentic_loopÚrequest_patchÚmetadata)r;   rå   r†   rÍ   rZ   r.   r/   rF   r   r  r  rý   rD   r<   r�   r7   r¯   rŸ   r©   r˜   r®   r�   r!   r"   Ú
startswith)rÐ   rˆ   rÓ   r=   r�   Ú"anthropic_messages_provider_configÚ*anthropic_messages_optional_request_paramsr‚   r.  r2  r’   r¬   Úvalid_hashesr•   rŽ   rŒ   r  ry   r:   Úfollow_up_messagesr§   Útool_resultsr<  ÚkÚvÚ"optional_params_without_max_tokensÚfull_model_nameÚagentic_paramsÚ	candidates                                r2   Úasync_build_agentic_loop_planz/HeadroomGuardrail.async_build_agentic_loop_planö  s  è ø€ ð 6;·Y±Y¸|ÈRÓ5Pˆ
à×"Ñ"Ô$Ü)¨+°vÓ>ˆÙ]d�t×5Ñ5×9Ñ9¸'ÄIÃKÐQTÐCUÓVÐWXÒYÔjsÓjuˆà@Bˆ	Øò 	,ˆBØŸ™˜{¨BÓ/ˆIÜ6@ÀÌDÔ6Q˜Ÿ™ v¨rÔ2ÐWYˆJÜ.8¸ÄDÔ.I�I—M‘M 'Ô*ÈtˆEô �:‹ lÑ2Ü$×,Ñ,ØaØôð -¨Z¨LÐ8aÐb‘à $× 3Ñ 3Ü" :›Ù(-œ#˜eœ*°4ð !4ó !÷ �ô !×&Ñ&Ð'SÐU_ÔadÐelÓamÔnØ×Ñ˜b '˜]Õ+ð+	,ô. & hÔ/Ü!% h£Ô2QÐRZÐ\eÓ2fÑ!fÑÜ,¨XÔ6Ü!% h£Ô2TÐU]Ð_hÓ2iÑ!iÑä'MÈhÐXaÓ'bÐàfo÷#ÙWbÐWYÐ[b˜°·±¸³È'ÓRð#ˆLñ #ô "& h£Ð3DÐ2EÑ!EÈÑ!TÐà(R×(VÑ(VÐWcÓ(dò )
Ðhn×hrÑhrØói
ˆ
ð H×MÑMÓO÷5
Ù�Q˜ÐSTÐXdÓSdˆAˆq‰Dð5
Ð*ñ 5
ð  ˆØÐ"Ü$+¨KÐ9MÈrÓ$R×$VÑ$VÐWlÐnpÓ$qˆNØ-×1Ñ1°'¸5ÓAˆIÜ˜)¤SÔ)©iØ"+�äØ!Ü1Ø%Ø+Ø%Ø Bà%+§\¡\£^÷Ù!˜Q ¸1¿<¹<ÈÕ;TÐYZÐ^sÓYs�A�q‘Dóôð " >Ð2ô
ð 	
ðAûó#ùó5
ùó$ùsQ   ‚DK$ÄKÄBK$Æ/KÇAK$ÈKÈ(KÈ-A,K$ÊKÊ3KÊ9KÊ>K$ËK$c                 ó   — ddl m}  | S )Nr   ©ÚHeadroomGuardrailConfigModel)Ú7litellm.types.proxy.guardrails.guardrail_hooks.headroomrV  rU  s    r2   Úget_config_modelz"HeadroomGuardrail.get_config_modelG  s   € õ	
ð ,Ð+r5   )Úreturnzlist[GuardrailEventHooks])NNNNNFN)rÑ   ú
str | NonerÒ   rZ  rÓ   rZ  rÁ   rZ  rÂ   z=GuardrailEventHooks | list[GuardrailEventHooks] | Mode | NonerÃ   r   rÊ   rZ  )rÚ   r/   rY  r   )rY  zdict[str, str])rY  ÚNone)r=   úlist[dict[str, object]]rç   rF   rè   údict[str, object]rY  r\  )r=   r\  rÓ   rZ  rY  z7tuple[list[dict[str, object]], bool, dict[str, object]]r-   )r  rF   ry   rZ  rY  rF   )
r#  r$   rÚ   r/   r$  zLiteral['request', 'response']r‚   úLiteLLMLoggingObj | NonerY  r$   )r2  zdict[str, Any]r3  zCallTypes | NonerY  zdict[str, Any] | None)r�   r   rÓ   rF   r=   ú
list[dict]rˆ   zlist[dict] | Noner.  r   r7  rF   r2  r/   rY  ztuple[bool, dict])rˆ   r/   rÓ   rF   r=   r_  r�   r   rH  r   rI  r/   r‚   r^  r.  r   r2  r/   rY  r!   )rY  z)type[GuardrailConfigModel[object]] | None)Ú__name__Ú
__module__Ú__qualname__r²   Ú__annotations__rZ   r)   r³   Úclassmethodr¸   rÏ   rÜ   rß   rå   rê   r	  r  r   r,  r/  r8  rS  ÚstaticmethodrX  Ú__classcell__)rÔ   s   @r2   r±   r±   X  sV  ø… Ø8<Ð% ~Ó<Ù<EÐGbÐFcÓ<dÐÐ!9Ódàò
ó ð
ð  $Ø"Ø Ø%)ØTXØ Ø+/ð
àð
ð ð
ð ð	
ð
 #ð
ð Rð
ð ð
ð )õ
ó@,óó
ðPà)ðPð ðPð "ð	Pð
 
!óPðU%à)ðU%ð ðU%ð 
Aó	U%ôn$ðL ð 15ðfTà)ðfTð ðfTð 3ð	fTð
 .ðfTð 
#òfTó ðfTðP
àð
ð $ð
ð 
õ	
ð&0àð0ð ð0ð ð	0ð
 !ð0ð ð0ð !ð0ð ð0ð 
ó0ð&O
àðO
ð ðO
ð ð	O
ð
 ðO
ð -0ðO
ð 59ðO
ð .ðO
ð ðO
ð ðO
ð 
óO
ðb ò,ó ô,r5   r±   )r1   rt   rY  zTypeGuard[dict[str, object]])r1   rt   rY  zTypeGuard[list[object]])r=   r\  rY  r\  )rG   r\  rH   r\  rY  r\  )r=   zSequence[Mapping[str, object]]rY  úfrozenset[int])r=   úSequence[dict[str, object]]ra   rh  r^   rg  rY  rh  )rg   rþ   rh   rF   rY  r]  )r=   r\  rY  z	list[str])rY  r]  )r‚   rt   rƒ   r]  rY  rZ  )rˆ   rt   rY  r   )r�   rt   rY  r\  )r�   rt   r•   z'Sequence[tuple[dict[str, object], str]]rY  r]  )r�   rt   rY  r   )r�   rt   r•   z#list[tuple[dict[str, object], str]]rY  r\  )UÚ
__future__r   r“   Úrerá   r!  Úcollections.abcr   r   Útypingr   r   r   r	   r
   r   rö   Úfastapir   r   ÚHttpxResponserû   Úlitellm._loggingr   Úlitellm.compression.compressr   Ú%litellm.integrations.custom_guardrailr   r   Ú3litellm.litellm_core_utils.prompt_templates.factoryr   r   r   r   Ú&litellm.llms.custom_httpx.http_handlerr   r   Ú5litellm.proxy.guardrails.guardrail_hooks.content_textr   r   r   r   Ú0litellm.proxy.spend_tracking.compression_savingsr   Úlitellm.secret_managers.mainr   Úlitellm.types.guardrailsr   r   Ú(litellm.types.integrations.custom_loggerr    r!   r"   Úlitellm.types.utilsr#   r$   Ú*litellm.litellm_core_utils.litellm_loggingr%   ÚLiteLLMLoggingObjÚ3litellm.types.proxy.guardrails.guardrail_hooks.baser&   r'   rc  r)   Úcompiler*   r+   r3   r8   rA   rN   r[   rd   rk   rq   r~   r†   r‰   r�   r˜   r�   rŸ   r©   r¯   r±   rR   r5   r2   ú<module>r~     sš  ðÞ "ã Û 	Û Û ß -ß J× Jã Ý !Ý +ã Ý 1Ý >÷÷ó ÷÷ó õ YÝ 7ß >÷ñ ÷
 EáÝWÝXà*€ˆuÓ *Ø%8Ð ˜UÓ 8Ø!�r—z‘zÐ"8Ó9€ˆuÓ 9Ø!(Ð ˜Ó (ó#ó#óð.Ø&ðØ2Iðàóó>ð$Ø)ðà+ðð &ðð !ó	ó$6ó*óó6GóBóðØðà6ðð óó:LóMð!-Øð!-à2ð!-ð ó!-ðHØðà2ðð óô6u,˜õ u,r5   