Ë
    tPêj7  ã                   ó‚   — d Z ddlmZ ddlmZ ddlmZ dedefd„Z	dede
fd„Zd	ee   d
edee   fd„Zdededz  fd„Zy)aÖ  Shared content-part helpers for compression guardrails (headroom, compresr).

Compression services only transform plain-string message content: every
transform in the service pipeline gates on ``isinstance(content, str)`` and
silently skips the OpenAI list-of-parts shape. Guardrails that send messages
to such a service collapse text-bearing part lists to strings here, and write
the rewritten text back through ``merge_rewritten_text_parts``.

Anthropic ``cache_control`` breakpoints are positional: each one caches the
prefix ending at the part that carries it. A single compressed string can
therefore only be written back over a run of text parts, never across a
non-text part, which is what ``is_all_text_parts`` gates.
é    )ÚSequence)ÚFinal)Úget_attribute_or_keyÚcontentÚreturnc                 ó.  — t        | t        «      r| S t        | t        «      rsg }| D ][  }t        |t        «      sŒ|j	                  d«      dk(  sŒ)|j	                  d«      }t        |t        «      sŒK|j                  |«       Œ] dj                  |«      S y)zÓCollapse a message ``content`` (str or list-of-parts) to plain text.

    For the multimodal list shape, joins ``{type: "text", text: ...}`` parts
    with blank-line separators; non-text parts are ignored.
    ÚtypeÚtextz

Ú )Ú
isinstanceÚstrÚlistÚdictÚgetÚappendÚjoin)r   ÚpartsÚpartr
   s       úz/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/guardrails/guardrail_hooks/content_text.pyÚcontent_to_textr      sƒ   € ô �'œ3ÔØˆÜ�'œ4Ô Ø"$ˆØò 	'ˆDÜ˜$¤Õ%¨$¯(©(°6Ó*:¸fÓ*DØ—x‘x Ó'�Ü˜d¤CÕ(Ø—L‘L Õ&ð		'ð
 �{‰{˜5Ó!Ð!Øó    c                 óL   — t        | t        «      r| syt        d„ | D «       «      S )zGTrue when ``content`` is a non-empty part list holding only text parts.Fc              3   óh   K  — | ]*  }t        |t        «      xr |j                  d «      dk(  –— Œ, y­w)r	   r
   N)r   r   r   ©Ú.0r   s     r   ú	<genexpr>z$is_all_text_parts.<locals>.<genexpr>,   s-   è ø€ ÒYÈŒz˜$¤Ó%ÒD¨$¯(©(°6Ó*:¸fÑ*DÓDÑYùs   ‚02)r   r   Úall)r   s    r   Úis_all_text_partsr   (   s#   € ä�gœtÔ$©GØÜÑYÐQXÔYÓYÐYr   r   Únew_textc                 ó�   — t        d„ | D «       «      }t        d„ |D «       «      }|ri |d   ¥d|i¥nd|dœ}|ri |¥d|d   i¥gS |gS )a‰  Collapse a rewritten all-text part list into one part carrying ``new_text``.

    Only all-text rows are ever flattened, so the merged part IS the whole row:
    it keeps the first part's fields and the LAST declared cache_control
    breakpoint. A breakpoint caches the prefix ending at its part, so after the
    merge the last one (and its TTL) is the one that still describes the row.
    c              3   óB   K  — | ]  }t        |t        «      sŒ|–— Œ y ­w)N)r   r   r   s     r   r   z-merge_rewritten_text_parts.<locals>.<genexpr>7   s   è ø€ ÒO t¼
À4ÌÕ8NœdÑOùs   ‚˜c              3   óJ   K  — | ]  }|j                  d «      €Œ|d    –— Œ y­w)Úcache_controlN)r   r   s     r   r   z-merge_rewritten_text_parts.<locals>.<genexpr>8   s$   è ø€ Òu¸ÈtÏxÉxÐXgÓOhÑOt˜t OÕ4Ñuùs   ‚#™
#r   r
   )r	   r
   r#   éÿÿÿÿ)Útuple)r   r   Ú
dict_partsÚbreakpointsÚbases        r   Úmerge_rewritten_text_partsr)   /   si   € ô ÑO¨uÔOÓO€JÜÑuÀÔuÓu€KÙ9CÐ5�Z ‘]Ð5 F¨HÒ5ÐRXÐbjÑIk€DÙ:EÐ6ˆtÐ6�_ k°"¡oÑ6ÐPÐPÈ4ÐPÐPr   ÚresponseNc                 óÄ  — t        | dd«      }t        |t        «      r.|r,t        |d   dd«      }|�t        t        |dd«      «      }|r|S t        | dd«      }t        |t        «      rS|D ��cg c]3  }t        |dd«      dk(  r!t        |dd«      }t        |t        «      r|r|‘Œ5 }}}|rdj                  |«      S t        | d	d«      }t        |t        «      r{|D ��	�cg c]Y  }t        |dd«      dk(  rGt        |dd«      xs d
D ]3  }	t        |	dd«      dk(  r!t        |	dd«      }t        |t        «      r|r|‘Œ5 Œ[ }
}	}}|
rdj                  |
«      S yc c}}w c c}}	}w )z×The assistant's natural-language text from a model response, across chat,
    Anthropic, and Responses shapes. Preserved when the turn is rebuilt for the
    retrieval follow-up so the model's reasoning is not lost.ÚchoicesNr   Úmessager   r	   r
   r   Úoutput© Úoutput_text)r   r   r   r   r   r   )r*   r,   r-   r
   r   Úblockr   r.   ÚitemÚchunkÚoutput_partss              r   Úassistant_text_from_responser5   =   s„  € ô *¨(°I¸tÓD€GÜ�'œ4Ô ¡WÜ-¨g°a©j¸)ÀTÓJˆØÐÜ)Ô*>¸wÈ	ÐSWÓ*XÓYˆDÙØ�Ü)¨(°I¸tÓD€GÜ�'œ4Ô ð !÷
àÜ# E¨6°4Ó8¸FÒBÜ-¨e°V¸TÓB�Ü˜$¤Ô$©ò	 ð
ˆñ 
ñ Ø—7‘7˜5“>Ð!Ü(¨°8¸TÓB€FÜ�&œ$Ôð ÷
ð 
àÜ# D¨&°$Ó7¸9ÒDÜ.¨t°YÀÓEÒKÈò	
ð Ü# E¨6°4Ó8¸MÒIÜ-¨e°V¸TÓB�Ü˜$¤Ô$©ò ð
Øð
ˆò 
ñ Ø—7‘7˜<Ó(Ð(Øùó-
ùô
s   Á.8EÃAE)Ú__doc__Úcollections.abcr   Útypingr   Ú3litellm.litellm_core_utils.prompt_templates.factoryr   Úobjectr   r   Úboolr   r   r)   r5   r/   r   r   ú<module>r<      s|   ðñõ %Ý å Tð˜Vð ¨ó ð&Z˜vð Z¨$ó ZðQ h¨vÑ&6ð QÀ#ð QÈ$ÈvÉ,ó Qð#¨6ð #°c¸D±jô #r   