
    jKj[                         d Z ddlmZmZmZmZmZmZ ddlm	Z	m
Z
mZ ddlmZ  G d ded      Z G d	 d
ed      Zdee   dee	   fdZdeeef   de
fdZdede
fdZdedee
   fdZdedee   fdZdedee   fdZdedee   fdZdeeef   dee   fdZ	 d'dededee
   fdZdedee
   fdZdedefdZdedefd Zdedefd!Zdedefd"Zdedeeeef      fd#Z d$eeee   f   dee
   fd%Z!defd&Z"y)(z
Gemini-specific conversion utilities.

This module handles the conversion of Gemini API responses and inputs
into standardized formats for PostHog tracking.
    )AnyDictListOptional	TypedDictUnion)FormattedContentItemFormattedMessage
TokenUsage)serialize_raw_usagec                       e Zd ZU dZeed<   y)
GeminiPartz&Represents a part in a Gemini message.textN)__name__
__module____qualname____doc__str__annotations__     s/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/posthog/ai/gemini/gemini_converter.pyr   r      s
    0
Ir   r   F)totalc                   d    e Zd ZU dZeed<   eeee	ee
f   f      ed<   eeee
   f   ed<   eed<   y)GeminiMessagez9Represents a Gemini message with various possible fields.rolepartscontentr   N)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s?    C
Ij$sCx.01223S	>""
Ir   r   r   returnc                    g }| D ]c  }t        |t              rd|v r|j                  d|d   d       0t        |t              r|j                  d|d       Ut        |t              rEd|v rA|d   }|j	                  dd      }|j                  d      rdnd}|j                  ||d	       t        |d      r%t        |dd      }|s|j                  d|d       t        |d      s|j                  }t        |d      rPt        |d
      rD|j                  }|j                  d      rdnd}|j                  |||j                  dd	       P|j                  d|d	       f |S )aB  
    Format Gemini parts array into structured content blocks.

    Preserves structure for multimodal content (text + images) instead of
    concatenating everything into a string.

    Args:
        parts: List of parts that may contain text, inline_data, etc.

    Returns:
        List of formatted content blocks
    r   typer   inline_data	mime_type zimage/imagedocument)r"   r#   data)r$   r(   )
isinstancedictappendr   get
startswithhasattrgetattrr#   r$   r(   )r   content_blockspartr#   r$   content_type
text_values          r   _format_parts_as_content_blocksr4   !   sx    24NdD!fn!!64<"HI c"!!64"@A d#(=}-K#R8I&/&:&:8&D7*L!!(#. T6" vr2J%%vz&JK T=)**K{K0W[&5Q'11	*3*>*>x*Hwj%% ,)2$/$4$4( %% ''2_ l r   itemc                    d| v r6t        | d   t              r#t        | d         }| j                  dd      |dS d| v re| d   }t        |t              r t        |      }| j                  dd      |dS t        |t              st	        |      }| j                  dd      |dS d| v r| j                  dd      | d   dS dt	        |       dS )z
    Format a dictionary message into standardized format.

    Args:
        item: Dictionary containing message data

    Returns:
        Formatted message with role and content
    r   r   userr   r   r   r   )r)   listr4   r,   r   )r5   r0   r   s      r   _format_dict_messager:   i   s     $:d7mT:8gG0^LL Dy/gt$<WEN HHVV4PPGS)'lG0WEE ~0T&\JJ s4y11r   c                    t        | d      rft        | j                  d      rPt        t        | j                              }t        | d      rt	        | dd      nd}t        |t              sd}||dS t        | d      r<t        | d      rt	        | dd      nd}t        |t              sd}|| j                  dS t        | d      ryt        | d      rt	        | dd      nd}t        |t              sd}| j                  }t        |t              rt        |      }||dS t        |t              st        |      }||dS dt        |       dS )z
    Format an object (with attributes) into standardized format.

    Args:
        item: Object that may have text or parts attributes

    Returns:
        Formatted message with role and content
    r   __iter__r   r7   r8   r   r   )	r.   r   r4   r9   r/   r)   r   r   r   )r5   r0   r   r   s       r   _format_object_messager=      s5    tW'$**j"A8djj9IJ07f0EwtVV,6 $$D88 tV07f0EwtVV,6 $$D33 tY07f0EwtVV,6 $$D,,gt$<WEN ^<<GS)'lG11 s4y11r   responsec                    g }| |S t        | d      r| j                  r| j                  D ]  }t        |d      r|j                  rzg }t        |j                  d      rG|j                  j                  r0|j                  j                  D ]  }t        |d      r+|j                  r|j                  d|j                  d       ;t        |d      rD|j                  r8|j                  }|j                  d|j                  |j                  d	d
       t        |d      s|j                  sddl
}|j                  }t        |dd      }t        |dd      }	t        |	t              r!|j                  |	      j                  d      }
n|	}
|j                  d||
d        |s|j                  d|d       t        |d      s|j                  s|j                  dd|j                  dgd        |S t        | d      r.| j                  r"|j                  dd| j                  dgd       |S )z
    Format a Gemini response into standardized message format.

    Args:
        response: The response object from Gemini API

    Returns:
        List of formatted messages with role and content
    N
candidatesr   r   r   r!   function_callfunctionname	argumentsr"   rB   r#   r   r$   z	audio/pcmr(   r   zutf-8audio)r"   r$   r(   	assistantr8   )r.   r@   r   r   r   r+   rA   rD   argsr#   base64r/   r)   bytes	b64encodedecode)r>   output	candidater   r1   rA   rJ   r#   r$   raw_datar(   s              r   format_gemini_responserQ      s    &(Fx&8+>+>!,,Iy),1B1B689,,g69;L;L;R;R ) 1 1 7 7"40TYY#NN,2,0II!" %T?;@R@R,0,>,>M#NN,60=0B0B5B5G5G1&!" %T=9d>N>N)*.*:*:K(/[+(VI'.{FC'HH  *(E:'-'7'7'A'H'H'Q (0#NN,31:,0!"I !8X MM$/'. F+	 +-3Y^^$L#Mu -R M 
6	"x}}#%+X]]CD	
 Mr   c                     | rYt        | d      rM| j                  rA| j                  d   }t        |dd      }|#t        |d      r|j                  S t	        |      S y)z)Extract stop reason from Gemini response.r@   r   finish_reasonNrD   )r.   r@   r/   rD   r   )r>   rO   rS   s      r   extract_gemini_stop_reasonrT   "  s^    GHl38K8K''*		?DA$}f-$)))}%%r   chunkc                     t        |       S )z2Extract stop reason from a Gemini streaming chunk.)rT   )rU   s    r   %extract_gemini_stop_reason_from_chunkrW   /  s    %e,,r   configc                     | yt        | d      r| j                  S t        | t              r	d| v r| d   S t        | t              r	d| v r| d   S y)z
    Extract system instruction from Gemini config parameter.

    Args:
        config: Config object or dict that may contain system instruction

    Returns:
        System instruction string if present, None otherwise
    Nsystem_instructionsystemInstruction)r.   rZ   r)   r*   )rX   s    r   !extract_gemini_system_instructionr\   4  sd     ~ v+,(((	FD	!&:f&D*++	FD	!&9V&C)**r   kwargsc                 H    d| v rt        | d   d      r| d   j                  S y)z
    Extract tool definitions from Gemini API kwargs.

    Args:
        kwargs: Keyword arguments passed to Gemini API

    Returns:
        Tool definitions if present, None otherwise
    rX   toolsN)r.   r_   )r]   s    r   extract_gemini_toolsr`   L  s.     6gfX&6@h%%%r   Ncontentsc                     t        |       }t        |      }|.t        d |D              }|sddlm} d|d}|gt        |      z   }|S )ax  
    Format Gemini input contents into standardized message format, including system instruction handling.

    Args:
        contents: Input contents in various possible formats
        config: Config object or dict that may contain system instruction

    Returns:
        List of formatted messages with role and content fields, with system message prepended if needed
    c              3   D   K   | ]  }|j                  d       dk(    yw)r   systemN)r,   ).0msgs     r   	<genexpr>z2format_gemini_input_with_system.<locals>.<genexpr>p  s      S@RH4@Rs    r   )r
   rd   r8   )format_gemini_inputr\   anyposthog.ai.typesr
   r9   )ra   rX   formatted_messagesrZ   
has_systemr
   system_messages          r   format_gemini_input_with_systemrn   ]  sd     -X6 ;6B%S@RSS
9 !-0N #1!1D9K4L!Lr   c                    t        | t              rd| dgS t        | t              rug }| D ]l  }t        |t              r|j                  d|d       (t        |t              r|j                  t        |             S|j                  t        |             n |S t        | t              rt        |       gS t        |       gS )a  
    Format Gemini input contents into standardized message format for PostHog tracking.

    This function handles various input formats:
    - String inputs
    - List of strings, dicts, or objects
    - Single dict or object
    - Gemini-specific format with parts array

    Args:
        contents: Input contents in various possible formats

    Returns:
        List of formatted messages with role and content fields
    r7   r8   )r)   r   r9   r+   r*   r:   r=   )ra   	formattedr5   s      r   rh   rh   }  s    $ (C H566 (D!,.	D$$  &T!BCD$'  !5d!;<   !7!=>   (D!$X.// #8,--r   c                    t        | d      rE| j                  r8| j                  D ](  }t        |d      rl|j                  r`|j                  }t        |d      r|j                  }|t	        |      dkD  r yt        |d      r|j
                  }|t	        |      dkD  r yt        |d      s|j                  st        |j                  d      s|j                  j                  s|j                  j                  D ]L  }t        |d	      s|j                  st        |j                  d
d      j                         }d|v sd|v sK  y + y)aO  
    Extract web search count from Gemini response.

    Gemini bills per request that uses grounding, not per query.
    Returns 1 if grounding_metadata is present with actual search data, 0 otherwise.

    Args:
        response: The response from Gemini API

    Returns:
        1 if web search/grounding was used, 0 otherwise
    r@   grounding_metadataweb_search_queriesr      grounding_chunksr   r   rA   rD   r%   google_search	grounding)r.   r@   rr   rs   lenru   r   r   rA   r/   lower)r>   rO   rr   querieschunksr1   function_names          r   extract_gemini_web_search_countr}     s5    x&8+>+>!,,I	#7800%.%A%A" -/CD0CCG*s7|a/?  -/AB/@@F)c&kAo  y),1B1B9,,g69;L;L;R;R ) 1 1 7 7"49d>P>P,3 $ 2 2FB-#eg *
 !0= @#.-#?'( !81 -H r   metadatac                     t        t        | dd      t        | dd            }t        | d      r| j                  }|r
|dkD  r||d<   t        | d      r| j                  }|r
|dkD  r||d<   t        |       }|r||d	<   |S )
z
    Common logic to extract usage from Gemini metadata.
    Used by both streaming and non-streaming paths.

    Args:
        metadata: usage_metadata from Gemini response or chunk

    Returns:
        TokenUsage with standardized usage
    prompt_token_countr   candidates_token_countinput_tokensoutput_tokenscached_content_token_countcache_read_input_tokensthoughts_token_countreasoning_tokens	raw_usage)r   r/   r.   r   r   r   )r~   usagecache_tokensr   
serializeds        r   _extract_usage_from_metadatar     s     X';Q?h(@!DE x56::L1,/;E+, x/0#88 01 4(8E$% %X.J'kLr   c                     t        | d      r| j                  st        dd      S t        | j                        }t	        |       }|dkD  r||d<   |S )z
    Extract usage statistics from a full Gemini response (non-streaming).

    Args:
        response: The complete response from Gemini API

    Returns:
        TokenUsage with standardized usage statistics
    usage_metadatar   r   web_search_count)r.   r   r   r   r}   )r>   r   r   s      r   "extract_gemini_usage_from_responser     sY     8-.h6M6Mq::()@)@AE 7x@!$4 !Lr   c                     t               }t        |       }|dkD  r||d<   t        | d      r| j                  s|S t	        | j                        }|j                  |       |S )z
    Extract usage statistics from a Gemini streaming chunk.

    Args:
        chunk: Streaming chunk from Gemini API

    Returns:
        TokenUsage with standardized usage statistics
    r   r   r   )r   r}   r.   r   r   update)rU   r   r   usage_from_metadatas       r   extract_gemini_usage_from_chunkr     sh     #E 7u=!$4 !5*+53G3G6u7K7KL 
LL$%Lr   c                 J   t        | d      r| j                  rd| j                  dS t        | d      r| j                  r| j                  D ]  }t        |d      s|j                  st        |j                  d      s4|j                  j                  sK|j                  j                  D ]r  }t        |d      r8|j
                  r,|j
                  }d|j                  |j                  dd	c c S t        |d      sT|j                  sad|j                  dc c S   y
)z
    Extract content (text or function call) from a Gemini streaming chunk.

    Args:
        chunk: Streaming chunk from Gemini API

    Returns:
        Content block dictionary if present, None otherwise
    r   r!   r@   r   r   rA   rB   rC   rF   N)r.   r   r@   r   r   rA   rD   rI   )rU   rO   r1   rA   s       r   !extract_gemini_content_from_chunkr   ;  s     uf%**

33 ul#(8(8))Iy),1B1B9,,g69;L;L;R;R ) 1 1 7 7"49d>P>P,0,>,>M(2,9,>,>1>1C1C-"$  %T62tyy,2DII#FF !8 *$ r   accumulated_contentc                 n   t        | t              r
dd| dgdgS t        | t              rg }g }| D ]  }t        |t              r|j                  |       %t        |t              s6|j                  d      dk(  r"|j                  |j                  dd             l|j                  d      dk(  s|r%|j                  ddj                  |      d       g }|j                  d|j                  di       d        |r#|j                  ddj                  |      d       |rd|dgS ddddgdgS )	z
    Format the final output from Gemini streaming.

    Args:
        accumulated_content: Accumulated content from streaming (string, list of strings, or list of content blocks)

    Returns:
        List of formatted messages
    rH   r   r!   r8   r"   r%   rB   rF   )r)   r   r9   r+   r*   r,   join)r   r   
text_partsr5   s       r   format_gemini_streaming_outputr   a  sK    %s+ $%+5HIJ
 	
 %t,.0
'D$$!!$'D$'88F#v-%%dhhvr&:;XXf%3!(.(*
(; &(
 NN$.(,R(@) (8 NN"GGJ/ (W=>> !vr.J-KLMMr   c                     d}t        | d      r_| j                  rS| j                  D ]D  }t        |d      s|j                  st        |j                  dd      }|7|t	        |      z  }F |S )z
    Extract total token count from a Gemini embed_content response.
    Token counts are only available per-embedding via Vertex AI's statistics.token_count.
    Returns 0 if no token counts are available.
    r   
embeddings
statisticstoken_countN)r.   r   r   r/   int)r>   r   	embeddingr   s       r   $extract_gemini_embedding_token_countr     sm     Ex&8+>+>!,,Iy,/I4H4H%i&:&:M4P*S--E	 -
 Lr   )N)#r   typingr   r   r   r   r   r   rj   r	   r
   r   posthog.ai.utilsr   r   r   r4   r   r:   r=   rQ   rT   rW   r\   r`   rn   rh   r   r}   r   r   r   r   r   r   r   r   r   <module>r      s   ? > 
 1% IU E49 E>R9S EP#2tCH~ #22B #2L32 32)9 32lZS ZT2B-C Zz
 
# 
- -# -
c hsm 0c3h HSM $ "&	
@*.# *.$/?*@ *.Z4c 4c 4n"3 ": "J  .3 : <#S #Xd38n5M #LDNsDI~.DN	
DNNc r   