o
    ٰi"                     @   s  d dl Z d dlZd dl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mZmZmZmZmZmZmZmZmZ d dlZd dlmZmZmZmZmZmZ d dlmZm Z  d d	l!m"Z" d d
l#m$Z$m%Z%m&Z& d dl'm(Z(m)Z)m*Z* d dl+m,Z, erd dl-m.Z. d dl	m/Z/ d dl'm0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6 G dd deZ7				djddZ8dkddZ9ddde:fddZ;dld"d#Z<dmd&d'Z=dmd(d)Z>dnd+d,Z?dod.d/Z@	0	1		2dpd3d4ZA		5		2dqd6d7ZB	8	9	:	;	<	=		;drd>d?ZCd@e:dAd-ddBfdCdDZDdsdFdGZE	H	I		IdtdJdKZF		5		LdudMdNZG		5		LdudOdPZHdQdRdSeIddTfdUdVZJ	Q	R		TdvdWdXZKdYdBdZdde:dd d:d;ddfd[d\ZL	Y	B	Z			5		dwd]d^ZM	8	9	:	;		_dxd`daZN	8	9	:	;		bdydcddZO	Y	B	Z				:	;		dzdedfZP	Y	B	Z			g		d{dhdiZQdS )|    N)wraps   )ORIGINTOOL_ATTRIBUTES_MAPGEN_AI_SYSTEM)BLOB_DATA_SUBSTITUTE)
castTYPE_CHECKINGIterableAnyCallableListOptionalUnion	TypedDictDict)set_data_normalizedtruncate_and_annotate_messagesnormalize_message_rolesredact_blob_message_partstransform_google_content_partget_modality_from_mime_type)OPSPANDATA)should_send_default_pii)capture_internal_exceptionsevent_from_exceptionsafe_serialize)GenerateContentConfigPartContent)chain)Span)TextPart)GenerateContentResponseContentListUnionContentUnionDictToolModelEmbedContentResponseContentUnionc                   @   s:   e Zd ZU dZeed< eed< eed< eed< eed< dS )	UsageDatazStructure for token usage data.input_tokensinput_tokens_cachedoutput_tokensoutput_tokens_reasoningtotal_tokensN)__name__
__module____qualname____doc__int__annotations__ r7   r7   ^/home/ubuntu/.local/lib/python3.10/site-packages/sentry_sdk/integrations/google_genai/utils.pyr+   5   s   
 r+   response.Union[GenerateContentResponse, dict[str, Any]]returnc           	      C   sl  t dddddd}t| trb| di }|s|S |ddpd}|ddp'd}|| |d< |ddp5d}||d< |d	dpAd}||d
< |ddpMd}|| |d< |ddp[d}||d< |S t| dsi|S | j}t|ddpsd}t|ddp{d}|| |d< t|ddpd}||d< t|d	dpd}||d
< t|ddpd}|| |d< t|ddpd}||d< |S )a@  Extract usage data from response into a structured format.

    Args:
        response: The GenerateContentResponse object or dictionary containing usage metadata

    Returns:
        UsageData: Dictionary with input_tokens, input_tokens_cached,
                   output_tokens, and output_tokens_reasoning fields
    r   )r,   r-   r.   r/   r0   usage_metadataprompt_token_counttool_use_prompt_token_countr,   cached_content_token_countr-   thoughts_token_countr/   candidates_token_countr.   total_token_countr0   )r+   
isinstancedictgethasattrr<   getattr)	r9   
usage_datausageprompt_tokenstool_use_prompt_tokenscached_tokensreasoning_tokenscandidates_tokensr0   r7   r7   r8   extract_usage_data?   sL   
	
rO   excr   c                 C   s0   t | t jdddd\}}tj||d dS )z.Capture exception with Google GenAI mechanism.google_genaiF)typehandled)client_options	mechanism)hintN)r   
sentry_sdk
get_clientoptionscapture_event)rP   eventrV   r7   r7   r8   _capture_exception   s   
r\   modelzUnion[str, Model]c                 C   s*   t | tr| S t| drt| jS t| S )z(Extract model name from model parameter.name)rC   strrF   r^   )r]   r7   r7   r8   get_model_name   s
   


r`   contentsr%   List[Dict[str, Any]]c                 C   s  | du rg S g }t | trd| dgS t | tr(| D ]}t|}|| q|S t | tr| dd}| d}|r~g }g }|D ]"}t|}	|	du rKq@t |	tr]|	ddkr]||	 q@||	 q@|rw|dkrkdn|pnd}
||
|d || |S d	| v r||pd| d	 d	d
gd |S t	| dr| j
rt| ddpd}g }g }| j
D ]"}t|}	|	du rqt |	tr|	ddkr||	 q||	 q|r|dkrdn|}
||
|d || |S t| }	|	rt |	tr|	ddkr|	gS d|	gdgS zddlm} t | |jr!t| }|r!d|gdgW S W n
 ty,   Y nw t	| drat	| drat| dd}t| dd}|dura|du rQd}dt|||d}d|gdgS t	| d	rx| jrxdt| jd	d
gdgS g S )a$  Extract messages from contents parameter which can have various formats.

    Returns a list of message dictionaries in the format:
    - System: {"role": "system", "content": "string"}
    - User/Assistant: {"role": "user"|"assistant", "content": [{"text": "...", "type": "text"}, ...]}
    Nuserrolecontentre   partstoolr]   	assistanttextrj   rR   r   Imageuri	mime_type rR   modalityro   rn   )rC   r_   listextract_contents_messagesextendrD   rE   _extract_part_contentappendrF   rg   rG   PILrm   _extract_pil_imageImportErrorr   rj   )ra   messagesitemitem_messagesre   rg   content_partstool_messagespartpart_resultnormalized_rolePILImage	blob_partfile_uriro   r7   r7   r8   rt      s   









rt   r   Optional[dict[str, Any]]c                 C   s|  | du rdS t | trDd| v rt| S | dr| d ddS t| }|durBd| v r@| d }t |tr@t |dtr@t|d< |S dS t| drP| jrPt| S t| dr^| j	r^| j	ddS t| dr| j
r| j
}t|d	d}t|d
d}|dur|du rd}dt|||dS t| dr| jr| j}t|dd}t|d
d}|dur|du rd}t |trt}n|}dt|||dS dS )zExtract content from a Part object or dict.

    Returns:
        - dict for content part (text/blob) or tool message
        - None if part should be skipped
    Nfunction_responserj   rk   inline_datadatarf   	file_datar   ro   rp   rn   rq   blobrR   rr   ro   rf   )rC   rD   _extract_tool_message_from_partrE   r   bytesr   rF   r   rj   r   rG   r   r   )r   resultr   r   r   ro   r   rf   r7   r7   r8   rv   #  sb   



rv   c                 C   s   d}t | tr| d}nt| dr| j}|sdS d}d}d}t |tr;|d}|d}|di }|d|}n&t|dd}t|dd}t|dd}|du rSi }t |tr_|d|}n|}|sedS d|rlt|ndt||durxt|nddd	S )
zExtract tool message from a Part with function_response.

    Returns:
        {"role": "tool", "content": {"toolCallId": "...", "toolName": "...", "output": "..."}}
        or None if not a valid tool message
    Nr   idr^   r9   outputrh   )
toolCallIdtoolNamer   rd   )rC   rD   rE   rF   r   rG   r_   r   )r   r   tool_call_id	tool_namer   response_dictresponse_objr7   r7   r8   r   {  s>   





r   imagec                 C   sd   z'ddl m} t| |jsW dS | jpd}| }d| }dt||tdW S  ty1   Y dS w )z'Extract blob part from PIL.Image.Image.r   rl   NJPEGzimage/r   r   )rx   rm   rC   formatlowerr   r   	Exception)r   r   
format_strsuffixro   r7   r7   r8   ry     s   

ry   Optional[str]c                 C   s   t | }|sdS g }|D ]1}|d}t|tr|| qt|tr=|D ]}t|tr<|ddkr<||dd q%q|rEd|S dS )zExtract text from contents parameter which can have various formats.

    This is a compatibility function that extracts text from messages.
    For new code, use extract_contents_messages instead.
    Nrf   rR   rj   rp    )rt   rE   rC   r_   rw   rs   rD   join)ra   r{   textsmessagerf   r   r7   r7   r8   extract_contents_text  s   


r   tools#Iterable[Tool | Callable[..., Any]]Optional[List[dict[str, Any]]]c              	   C   s   g }| D ]Q}t |r|t|ddt|ddd qt|dr<|jdur<|jD ]}|t|ddt|ddd q(qt D ]\}}t||drT|||d  nq@q|rZ|S dS )	z%Format tools parameter for span data.r1   unknownr4   N)r^   descriptionfunction_declarationsr^   r   )callablerw   rG   rF   r   r   items)r   formatted_toolsrh   	func_decl	attr_namer   r7   r7   r8   _format_tools_for_span  s:   






	r   r$   c                 C   s  g }t | dg rF| jD ]:}t|drt |jdg sq|jjD ]&}t |ddrD|j}t |dddd}t |ddr?t|j|d	< || qqt | d
dr| j	D ]5}t |ddsXqOt |dg D ]%}t |ddr|j}t |dddd}t|dr~t|j|d	< || q^qO|r|S dS )z\Extract tool/function calls from response candidates and automatic function calling history.
candidatesrf   rg   function_callNr^   )r^   rR   args	arguments"automatic_function_calling_history)
rG   r   rF   rf   rg   r   r   r   rw   r   )r9   
tool_calls	candidater   r   	tool_callrf   r7   r7   r8   extract_tool_calls  sD   






r   r   tuple[Any, ...]kwargsdict[str, Any]rh   r'   c                 C   s~   |r|  ni }| r=z$t|}t|j }t| D ]\}}|t|k r+|||| < qW |S  ty<   | |d< Y |S w |S )z(Capture tool input from args and kwargs.r   )	copyinspect	signaturers   
parameterskeys	enumeratelenr   )r   r   rh   
tool_inputsigparam_namesiargr7   r7   r8   _capture_tool_input=  s    

r   r   tool_docr"   c                 C   sJ   t jtjd|  td}|tj|  |tjd |r#|tj	| |S )z!Create a span for tool execution.zexecute_tool )opr^   originfunction)
rW   
start_spanr   GEN_AI_EXECUTE_TOOLr   set_datar   GEN_AI_TOOL_NAMEGEN_AI_TOOL_TYPEGEN_AI_TOOL_DESCRIPTION)r   r   spanr7   r7   r8   _create_tool_spanR  s   r   Tool | Callable[..., Any]c                    sd   t  s S t dd jt r#t d fdd}|S t d fd	d
}|S )z3Wrap a tool to emit execute_tool spans when called.r1   r   r   r   r   r;   c                     s   t e}t| | }t  |tjt| W d    n1 s$w   Y  z0 | i |I d H }t  |tjt| W d    n1 sKw   Y  |W W  d    S  tyj } zt	|  d }~ww 1 snw   Y  d S N
r   r   r   r   r   GEN_AI_TOOL_INPUTr   GEN_AI_TOOL_OUTPUTr   r\   r   r   r   r   r   rP   rh   r   r   r7   r8   async_wrappedk  s.   

z#wrapped_tool.<locals>.async_wrappedc                     s   t b}t| | }t  |tjt| W d    n1 s#w   Y  z- | i |}t  |tjt| W d    n1 sGw   Y  |W W  d    S  tyf } zt	|  d }~ww 1 sjw   Y  d S r   r   r   r   r7   r8   sync_wrapped  s,   

z"wrapped_tool.<locals>.sync_wrappedN)r   r   r   r   r;   r   )r   rG   r4   r   iscoroutinefunctionr   )rh   r   r   r7   r   r8   wrapped_tool`  s   
r   configr   c                 C   s4   | rt | dds
| S t| }dd | jD |_|S )zWrap tools in config to emit execute_tool spans. Tools are sometimes passed directly as
    callable functions as a part of the config object.r   Nc                 S   s   g | ]}t |qS r7   )r   ).0rh   r7   r7   r8   
<listcomp>  s    z-wrapped_config_with_tools.<locals>.<listcomp>)rG   r   r   )r   r   r7   r7   r8   wrapped_config_with_tools  s
   
r   Optional[List[str]]c                 C   sn   | rt | dg s
dS g }| jD ]!}t|drt|jdsq|jjD ]}t |ddr/||j q!q|r5|S dS )z&Extract text from response candidates.r   Nrf   rg   rj   )rG   r   rF   rf   rg   rw   rj   )r9   r   r   r   r7   r7   r8   _extract_response_text  s   
r   c                 C   sf   | rt | dg s
dS g }| jD ]}t |ddr,t|j}d|v r'|dd }|| q|r1|S dS )z0Extract finish reasons from response candidates.r   Nfinish_reason.)rG   r   r_   r   splitrw   )r9   finish_reasonsr   reasonr7   r7   r8   extract_finish_reasons  s   


r   system_instructions%Union[ContentUnionDict, ContentUnion]can_be_contentlist[TextPart]c                 C   s(  g }t | trd| dgS t | tr| jrd| jdgS |r@t | tr@t | jtr>| jD ]}t |jtr=|d|jd q,|S t | trR| 	drRd| d dgS |rt | tr| 	dg }|D ].}t |trxt |jtrx|d|jd qat |trt |	dtr|d|d d qa|S |S )Nrj   )rR   rf   rg   )
rC   r_   r   rj   r    rg   rs   rw   rD   rE   )r   r   
text_partsr   rg   r7   r7   r8   '_transform_system_instruction_one_level  s0   

r   c                 C   s6   g }t | trttdd | D }|S t| ddS )Nc                 s   s    | ]	}t |d dV  qdS )Fr   N)r   )r   instructionsr7   r7   r8   	<genexpr>  s    
z1_transform_system_instructions.<locals>.<genexpr>Tr   )rC   rs   r!   from_iterabler   )r   r   r7   r7   r8   _transform_system_instructions  s   

	r   r   integrationc                 C   s  |  tjt |  tj| |ddr|  tjd |d}t ry|jryg }d}|r5t|dr5|j	}nt
|trCd|v rC|d}|durS|  tjtt| t|}|| |ryt|}	t }
t|	| |
}|duryt| tj|dd dtjfd	tjfd
tjfdtjfdtjfdtjfdtjffD ]\}}t||rt||}|dur|  || q|durt|dr|j }|rt!|}|rt| tj"|dd dS dS dS dS dS )zSet span data for the request.streamFTr   Nsystem_instructionunpacktemperaturetop_ptop_kmax_output_tokenspresence_penaltyfrequency_penaltyseedr   )#r   r   r   GEN_AI_REQUEST_MODELrE   GEN_AI_RESPONSE_STREAMINGr   include_promptsrF   r   rC   rD   GEN_AI_SYSTEM_INSTRUCTIONSjsondumpsr   rt   ru   r   rW   get_current_scoper   r   GEN_AI_REQUEST_MESSAGESGEN_AI_REQUEST_TEMPERATUREGEN_AI_REQUEST_TOP_PGEN_AI_REQUEST_TOP_KGEN_AI_REQUEST_MAX_TOKENSGEN_AI_REQUEST_PRESENCE_PENALTY GEN_AI_REQUEST_FREQUENCY_PENALTYGEN_AI_REQUEST_SEEDrG   r   r   GEN_AI_REQUEST_AVAILABLE_TOOLS)r   r   r]   ra   r   r   r{   r   contents_messagesnormalized_messagesscopemessages_dataparamspan_keyvaluer   r   r7   r7   r8   set_span_data_for_request  sv   


	
	

r  c                 C   s4  |sdS t  r|jrt|}|r| tjt| t|}|r(| tjt| t	|}|r5t
| tj| t|ddrC| tj|j t|ddrQ| tj|j t|}|d rb| tj|d  |d ro| tj|d  |d r|| tj|d  |d r| tj|d  |d r| tj|d  dS dS )	zSet span data for the response.Nresponse_idmodel_versionr,   r-   r.   r/   r0   )r   r  r   r   r   GEN_AI_RESPONSE_TEXTr   r   GEN_AI_RESPONSE_TOOL_CALLSr   r   GEN_AI_RESPONSE_FINISH_REASONSrG   GEN_AI_RESPONSE_IDr  GEN_AI_RESPONSE_MODELr  rO   GEN_AI_USAGE_INPUT_TOKENS GEN_AI_USAGE_INPUT_TOKENS_CACHEDGEN_AI_USAGE_OUTPUT_TOKENS$GEN_AI_USAGE_OUTPUT_TOKENS_REASONINGGEN_AI_USAGE_TOTAL_TOKENS)r   r   r9   response_textsr   r   rH   r7   r7   r8   set_span_data_for_response`  sH   r*  tuple[Any, Any, str]c                 C   sj   | r| d n| dd}t| dkr| d n| d}t|}| d}t|}||ur0||d< |||fS )zBExtract and prepare common arguments for generate_content methods.r   r]   r   r   ra   r   )rE   r   r`   r   )r   r   r]   ra   
model_namer   wrapped_configr7   r7   r8   prepare_generate_content_args  s   

r.  tuple[str, Any]c                 C   s&   | dd}| d}t|}||fS )zxExtract and prepare common arguments for embed_content methods.

    Returns:
        tuple: (model_name, contents)
    r]   r   ra   )rE   r`   )r   r   r]   ra   r,  r7   r7   r8   prepare_embed_content_args  s   
r0  c                 C   s   t  r?|jrA|rCg }t|tr|g}nt|tr)|D ]}t|}|r'|| qn	t|}|r2|g}|rEt| tj	|dd dS dS dS dS dS )z$Set span data for embedding request.Fr   N)
r   r  rC   r_   rs   r   rw   r   r   GEN_AI_EMBEDDINGS_INPUT)r   r   ra   r   input_textsr|   rj   r7   r7   r8   set_span_data_for_embed_request  s2   



r3  r)   c                 C   s   |sdS t |dr:|jr<d}|jD ]}t |dr,|jr,t|jdd}|dur,|t|7 }q|dkr>| tj| dS dS dS dS )z%Set span data for embedding response.N
embeddingsr   
statisticstoken_count)rF   r4  r5  rG   r5   r   r   r$  )r   r   r9   r0   	embeddingr6  r7   r7   r8    set_span_data_for_embed_response  s   

r8  )r9   r:   r;   r+   )rP   r   r;   N)ra   r%   r;   rb   )r   r   r;   r   )r   r   r;   r   )ra   r%   r;   r   )r   r   r;   r   )r9   r$   r;   r   )r   r   r   r   rh   r'   r;   r   )rh   r   r;   r   )r   r   r;   r   )r9   r$   r;   r   )r   r   r;   r   )r   r"   r   r   r9   r$   r;   N)r   r   r   r   r;   r+  )r   r   r   r   r;   r/  )
r   r"   r   r   ra   r   r   r   r;   N)r   r"   r   r   r9   r)   r;   N)Rr   r	  r   	functoolsr   constsr   r   r   sentry_sdk._typesr   typingr   r	   r
   r   r   r   r   r   r   r   rW   sentry_sdk.ai.utilsr   r   r   r   r   r   sentry_sdk.constsr   r   sentry_sdk.scoper   sentry_sdk.utilsr   r   r   google.genai.typesr   r   r    	itertoolsr!   sentry_sdk.tracingr"   r#   r$   r%   r&   r'   r(   r)   r*   r+   rO   r\   r_   r`   rt   rv   r   ry   r   r   r   r   r   r   r   r   r   boolr   r   r  r*  r.  r0  r3  r8  r7   r7   r7   r8   <module>   s   0 $


K


 

X
5

*
5

A



"

P
6


 