
    jKjyj                        d Z ddlmZmZmZmZ ddlmZmZm	Z	m
Z
mZmZ ddlmZ dedee
   fdZ	 dd	eeeeef         d
ee   dee
   fdZdeeef   dee   fdZ	 d dedeeeeef         dee   fdZdedefdZdedee   fdZdedefdZ	 d!dededefdZ	 d!dededee   fdZdedeeeeef         fdZdeeeeef   f   deeeef      ddfdZ	 	 d"dededeeeeef         dee
   fdZ	 d!deeef   dedefdZy)#z
OpenAI-specific conversion utilities.

This module handles the conversion of OpenAI API responses and inputs
into standardized formats for PostHog tracking. It supports both
Chat Completions API and Responses API formats.
    )AnyDictListOptional)FormattedContentItemFormattedFunctionCallFormattedImageContentFormattedMessageFormattedTextContent
TokenUsage)serialize_raw_usageresponsereturnc                 L   g }| |S t        | d      rg }d}| j                  D ]  }t        |d      s|j                  s|j                  j                  r|j                  j                  }|j                  j                  r(|j                  d|j                  j                  d       t        |j                  d      r{|j                  j                  re|j                  j                  D ]L  }|j                  d|j                  |j                  j                  |j                  j                  dd	       N t        |j                  d
      s1|j                  j                  sI|j                  j                  j                         }|j                  dd
i|        |r|j                  ||d       t        | d      rg }d}| j                  D ]  }|j                  dk(  r9|j                  }t        |d      rt        |j                  t               r|j                  D ]  }t        |d      r:|j                  dk(  r+t        |d      r|j                  d|j"                  d       It        |d      r|j                  d|j"                  d       tt        |d      s|j                  dk(  st        |d      sd|j$                  d}	|j                  |	        t        |d      s"dt'        |j                        d}
|j                  |
       Mt        |d      s[|j                  dk(  sl|j                  dt)        |dt)        |dd            |j                  t)        |di       dd	        |r|j                  ||d       |S )a  
    Format an OpenAI response into standardized message format.

    Handles both Chat Completions API and Responses API formats.

    Args:
        response: The response object from OpenAI API

    Returns:
        List of formatted messages with role and content
    choices	assistantmessagetexttyper   
tool_callsfunctionname	argumentsr   idr   audior   rolecontentoutputr!   output_textinput_image	image_urlimage)r   r&   function_callcall_idr    r   )hasattrr   r   r    r!   appendr   r   r   r   r   r   
model_dumpr"   r   
isinstancelistr   r%   strgetattr)r   r"   r!   r    choice	tool_call
audio_dictitemcontent_itemimage_contenttext_contents              s/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/posthog/ai/openai/openai_converter.pyformat_openai_responser9      s    &(F x#.0&&Fvy)fnn>>&&!>>..D>>))NN$*$*NN$:$: 6>><8V^^=V=V%+^^%>%>	(2&/ll,5,>,>,C,C1:1C1C1M1M-"	 &? 6>>738L8L!'!5!5!@!@!BJNNFG#Bz#BC= '@ MM & x"OODyyI%yy4+
4<<0N(,#L&9 , 1 1] B 'f =#NN,2,8,=,=!" %\6:#NNFLDUDU+VW $L&9 , 1 1] B 'k B )0)5)?)?DM $NN=93 )56 T9-,2C<M#NLNN<0v&499+G *%dIwtT27NO$(II)0{B)G%	K $` MM & M    Nmessages
input_datac                    g }| ;| D ]6  }|j                  |j                  dd      |j                  dd      d       8 |t        |t              rt|D ]m  }d}d}t        |t              r%|j                  dd      }|j                  dd      }nt        |t
              r|}nt        |      }|j                  ||d       o |S t        |t
              r|j                  d|d       |S |j                  dt        |      d       |S )a9  
    Format OpenAI input messages.

    Handles both messages parameter (Chat Completions) and input parameter (Responses API).

    Args:
        messages: List of message dictionaries for Chat Completions API
        input_data: Input data for Responses API

    Returns:
        List of formatted messages
    r    userr!   r)   r   )r+   getr-   r.   dictr/   )r;   r<   formatted_messagesmsgr4   r    r!   s          r8   format_openai_inputrC      s     24 C%%GGFF3"wwy"5  j$'"dD)88FF3D"hhy"5Gc*"G "$iG"))4G*LM #,  
C(%%v*&MN
  %%v#j/&RSr:   kwargsc                 (    d| v r| d   S d| v r| d   S y)z
    Extract tool definitions from OpenAI API kwargs.

    Args:
        kwargs: Keyword arguments passed to OpenAI API

    Returns:
        Tool definitions if present, None otherwise
    tools	functionsN )rD   s    r8   extract_openai_toolsrI      s.     &g fk""r:   accumulated_contentr   c                     g }| rd| d}|j                  |       |r=|D ]8  }d|j                  d      |j                  di       d}|j                  |       : |S )aJ  
    Format content from OpenAI streaming response.

    Used by streaming handlers to format accumulated content.

    Args:
        accumulated_content: Accumulated text content from streaming
        tool_calls: Optional list of tool calls accumulated during streaming

    Returns:
        List of formatted content items
    r   r   r   r   r   )r+   r?   )rJ   r   	formattedr7   r2   r'   s         r8   format_openai_streaming_contentrM      sv     -/I '.
 	& #I"mmD)%MM*b94M
 ]+ $ r:   c                 @   t        | d      rHd}| j                  D ]$  }t        |d      s|j                  dk(  s |dz  }& t        d|      }|dkD  r|S t        | d      rt	        | d      }|rt        |      dkD  ryt        | d      rt	        | d      }|rt        |      dkD  ryt        | d      r-t        | j                  d	      r| j                  j                  ryt        | d
      r| j                  D ]  }t        |d      rkt        |j                  d      rU|j                  j                  }|r=|D ]8  }t        |t              r|j                  d      nt	        |dd      }|dk(  s7  y t        |d      st        |j                  d      s|j                  j                  }|s|D ]8  }t        |t              r|j                  d      nt	        |dd      }|dk(  s7  y  t        | d      r| j                  D ]  }t        |d      st        |j                  t               s+|j                  D ]\  }	t        |	d      s|	j                  }|s|D ]9  }t        |t              r|j                  d      nt	        |dd      }|dk(  s7   y ^  y)aQ  
    Extract web search count from OpenAI response.

    Uses a two-tier detection strategy:
    1. Priority 1 (exact count): Check for output[].type == "web_search_call" (Responses API)
    2. Priority 2 (binary detection): Check for various web search indicators:
       - Root-level citations, search_results, or usage.search_context_size (Perplexity)
       - Annotations with type "url_citation" in choices/output (including delta for streaming)

    Args:
        response: The response from OpenAI API

    Returns:
        Number of web search requests (exact count or binary 1/0)
    r"   r   r   web_search_call   	citationssearch_resultsusagesearch_context_sizer   r   annotationsNurl_citationdeltar!   )r*   r"   r   maxr0   lenrS   rT   r   r   rU   r-   r@   r?   rW   r!   r.   )
r   web_search_countr4   rQ   rR   r1   rU   
annotationannotation_typer5   s
             r8   extract_openai_web_search_countr]   	  so   $ x"OODtV$6G)G A%  $ q"23a##
 x%Hk2	Y!+x)* +;<c.1A5x!ghnn>S&T>>-- x#&&Fvy)gfnnm.T$nn88&1
  **d; 'NN62!(VT!B ( +n<#$ '2 vw'GFLL-,P$ll66&1
  **d; 'NN62!(VT!B ( +n<#$ '2- 'D x"OODtY'Jt||T,J$(LLL|];&2&>&>&.9
 (2*d'C %/NN6$:)0VT)J !0 $3n#D+, /: %1 $$ r:   c                     t        | d      r&| j                  rt        | j                  d   dd      S t        | d      rt        | dd      S y)z)Extract stop reason from OpenAI response.r   r   finish_reasonNstatus)r*   r   r0   )r   s    r8   extract_openai_stop_reasonra   t  sL     x#(8(8x''*OTBBx"x400r:   c                    t        | d      st        dd      S d}d}d}d}t        | j                  d      r| j                  j                  }t        | j                  d      r| j                  j                  }t        | j                  d      r@t        | j                  j
                  d      r | j                  j
                  j                  }t        | j                  d      r@t        | j                  j                  d	      r | j                  j                  j                  }t        | j                  d
      r| j                  j                  }t        | j                  d      r| j                  j                  }t        | j                  d      r@t        | j                  j                  d      r | j                  j                  j                  }t        | j                  d      r@t        | j                  j                  d	      r | j                  j                  j                  }t        ||      }|
|dkD  r||d<   |
|dkD  r||d	<   t        |       }|dkD  r||d<   t        | j                        }|r||d<   |S )a  
    Extract usage statistics from a full OpenAI response (non-streaming).
    Handles both Chat Completions and Responses API.

    Args:
        response: The complete response from OpenAI API

    Returns:
        TokenUsage with standardized usage statistics
    rS   r   )input_tokensoutput_tokensrc   rd   input_tokens_detailscached_tokensoutput_tokens_detailsreasoning_tokensprompt_tokenscompletion_tokensprompt_tokens_detailscompletion_tokens_detailscache_read_input_tokensrZ   	raw_usage)r*   r   rS   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   r]   r   )r   rf   rc   rd   rh   resultrZ   
serializeds           r8   "extract_openai_usage_from_responserq     s!    8W%q::MLM x~~~.~~22x~~/ 44x~~567++_< !;;IIx~~67G,,.@= $>>??PP x~~/~~33x~~23 88x~~67G,,o= !<<JJx~~:;002DA $>>CCTT!#F
  ]Q%6,9()#(81(<%5!"6x@!%5!" %X^^4J({Mr:   chunkprovider_typec                 8   t               }|dk(  r;t        |       }|dkD  r||d<   t        | d      r| j                  s|S t	        | j                  dd      |d<   t	        | j                  dd      |d<   t        | j                  d	      rGt        | j                  j
                  d
      r'| j                  j
                  j                  }|||d<   t        | j                  d      rGt        | j                  j                  d      r'| j                  j                  j                  }|||d<   t        | j                        }|r||d<   |S |dk(  rHt        | d      r;| j                  dk(  r+t        | d      rt        | j                  d      r| j                  j                  r| j                  j                  }t	        |dd      |d<   t	        |dd      |d<   t        |d      r3t        |j                  d
      r|j                  j                  }|||d<   t        |d      r3t        |j                  d      r|j                  j                  }|||d<   t        | d      rt        | j                        }|dkD  r||d<   t        |      }|r||d<   |S )aC  
    Extract usage statistics from an OpenAI streaming chunk.

    Handles both Chat Completions and Responses API formats.

    Args:
        chunk: Streaming chunk from OpenAI API
        provider_type: Either "chat" or "responses" to handle different API formats

    Returns:
        Dictionary of usage statistics
    chatr   rZ   rS   ri   rc   rj   rd   rk   rf   rm   rl   rh   rn   	responsesr   response.completedr   re   rg   )r   r]   r*   rS   r0   rk   rf   rl   rh   r   r   r   re   rg   )rr   rs   rS   rZ   cached	reasoningrp   response_usages           r8   extract_openai_usage_from_chunkr{     s     #E ;5Aa(8E$%ug&ekkL !(_a Hn!(6I1!Mo 5;; 78WKK-->
 [[66DDF!39/0 5;; ;<KK113EB
 ==NNI$,5() )5
!+E+T LQ 
+	%5&!ejj4H&Hz*ENNG4NN((!&!5!5(/PQ(Rn%)0RS)To& >+ABw"77H ,@@NNF);A78 >+BC"88:LI !/ D D U UI ,4=01 5*-'Fu~~'V$'!+4D01 1@
)3E+&Lr:   c                    |dk(  rt        | d      r| j                  rwt        | j                        dkD  r_| j                  d   j                  rF| j                  d   j                  j                  r#| j                  d   j                  j                  S y|dk(  rrt        | d      rf| j
                  dk(  rWt        | d      rK| j                  r?| j                  }|j                  r't        |j                        dkD  r|j                  d   S y)	aC  
    Extract content from an OpenAI streaming chunk.

    Handles both Chat Completions and Responses API formats.

    Args:
        chunk: Streaming chunk from OpenAI API
        provider_type: Either "chat" or "responses" to handle different API formats

    Returns:
        Text content if present, None otherwise
    ru   r   r   rv   r   rw   r   N)r*   r   rY   rW   r!   r   r   r"   )rr   rs   ress      r8   !extract_openai_content_from_chunkr~   (  s       E9%EMM"Q&a &&a &&..==#))111  
+	%5&!ejj4H&Huj)ennnn::#cjj/A"5::a=(r:   c                    t        | d      r| j                  rt        | j                        dkD  r| j                  d   j                  rt        | j                  d   j                  d      ri| j                  d   j                  j                  rEg }| j                  d   j                  j                  D ]  }dt        |dd      i}t        |d      r|j                  r|j                  |d<   t        |d      r|j                  r|j                  |d<   t        |d      r|j                  ri }t        |j                  d	      r/|j                  j                  r|j                  j                  |d	<   t        |j                  d
      r/|j                  j                  r|j                  j                  |d
<   ||d<   |j                  |        |S y)z
    Extract tool calls from an OpenAI streaming chunk.

    Args:
        chunk: Streaming chunk from OpenAI API

    Returns:
        List of tool call deltas if present, None otherwise
    r   r   r   indexNr   r   r   r   r   )r*   r   rY   rW   r   r0   r   r   r   r   r   r+   )rr   r   r2   tc_dictfunction_dicts        r8   $extract_openai_tool_calls_from_chunkr   O  s    	y!MM"MM!""EMM!$**L9MM!""--
q)//::IGT:G y$'ILL )y&)inn"+..y*-)2D2D "9--v69;M;M;R;R,5,>,>,C,CM&)I..<!**441:1C1C1M1MM+.&3
#g&- ;. r:   accumulated_tool_callschunk_tool_callsc                     |D ]  }|j                  d      }||| vrdddddd| |<   | |   }d|v r|d   r|d   |d<   d|v r|d   r|d   |d<   d|v sS|d   }d	|v r|d	   r|d	   |d   d	<   d
|v sq|d
   sw|d   d
xx   |d
   z  cc<    y)a  
    Accumulate tool calls from streaming chunks.

    OpenAI sends tool calls incrementally:
    - First chunk has id, type, function.name and partial function.arguments
    - Subsequent chunks have more function.arguments

    Args:
        accumulated_tool_calls: Dictionary mapping index to accumulated tool call data
        chunk_tool_calls: List of tool call deltas from current chunk
    r   Nr)   r   r   )r   r   r   r   r   r   r   )r?   )r   r   tool_call_deltar   tc
func_deltas         r8   accumulate_openai_tool_callsr   ~  s     ,##G,= .."!#-"5) $E*?"t'<&t,BtH_$)@(0BvJ((4J#
6(:)3F);:v&j(Z-D:{+z+/FF+? ,r:   c                    |dk(  rg }t        | t              r| r|j                  d| d       n>t        | t              r.dj	                  d | D              }|r|j                  d|d       |r6|D ]1  }d|v sd|j                  dd      |d   d}|j                  |       3 |rd	|d
gS d	g d
gS |dk(  r.t        | t              r| r| S t        | t              r
d	d| dgd
gS d	dt        |       dgd
gS )aj  
    Format the final output from OpenAI streaming.

    Args:
        accumulated_content: Accumulated content from streaming (string for chat, list for responses)
        provider_type: Either "chat" or "responses" to handle different API formats
        tool_calls: Optional list of accumulated tool calls

    Returns:
        List of formatted messages
    ru   r   r   r)   c              3   8   K   | ]  }|st        |        y wN)r/   ).0r4   s     r8   	<genexpr>z1format_openai_streaming_output.<locals>.<genexpr>  s     M1D3t91Ds   r   r   r   r   r   rv   )r-   r/   r+   r.   joinr?   )rJ   rs   r   content_itemsr   r2   r'   s          r8   format_openai_streaming_outputr     sA   " 46 )3/4G  &:M!NO+T277M1DMMD$$fd%CD '	* *'mmD"5$-j$9<M
 "((7 ( (]CDD )R899	+	%)405H&&+S1 ()/9L MN   !'5H1IJK	
 r:   api_typec                      ddl m}  || d      S )z
    Format OpenAI streaming input based on API type.

    Args:
        kwargs: Keyword arguments passed to OpenAI API
        api_type: Either "chat" or "responses"

    Returns:
        Formatted input ready for PostHog tracking
    r   )merge_system_promptopenai)posthog.ai.utilsr   )rD   r   r   s      r8   format_openai_streaming_inputr     s     5vx00r:   )NNr   )ru   )ru   N)__doc__typingr   r   r   r   posthog.ai.typesr   r   r	   r
   r   r   r   r   r9   r/   rC   rI   rM   intr]   ra   rq   r{   r~   r   r   r   r   rH   r:   r8   <module>r      sQ   - ,  1|S |T2B-C |@ RV5tDcN+,5AI#5	
5pc3h HSM . LP##*24S#X3G*H#	
#Lhc hc hV # C C CN &,``"``H &,$$"$c]$N, ,d3PS8nAU8V ,^.G d38n!45.G4S>*.G 
.Gf  15BBB d38n-.B 

	BL -31cN1&)11r:   