
    jKjs                        d dl 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mZmZmZ d dlmZ d dlmZmZmZmZ d dlmZmZmZ d dlmZ  eh d      Zd	eeef   d
eeeef      defdZ dedeeeef      fdZ!	 d.dedededdfdZ"deeef   deeef   fdZ#dedefdZ$defdZ%dededee   fdZ&dedeeef   fdZ'deeef   dedee   fdZ(dee   dededee   d
eeeef      de)d eeeef      d!ed"ed#ef   dedefd$Z*dee   dededee   d
eeeef      de)d eeeef      d!ed%ed#ef   dedefd&Z+d'ededefd(Z,ded)e)d*efd+Z-ded,efd-Z.y)/    N)AnyCallableDictListOptionalcast)get_tagsidentify_contextnew_contexttagcontexts)warn_if_posthog_ai_gateway)sanitize_anthropicsanitize_geminisanitize_langchainsanitize_openai)FormattedMessageStreamingEventData
TokenUsage)Client>   $ai_total_tokens$ai_input_tokens$ai_output_tokens$ai_reasoning_tokens$ai_cache_read_input_tokens$ai_cache_creation_input_tokenssdk_tagsposthog_propertiesreturnc                 <    rt        fdt        D              ryy)Nc              3   &   K   | ]  }|v  
 y wN ).0keyr   s     a/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/posthog/ai/utils.py	<genexpr>z%_get_tokens_source.<locals>.<genexpr>    s      "-Ac!!-As   passthroughsdk)any_TOKEN_PROPERTY_KEYS)r   r   s    `r&   _get_tokens_sourcer,      s$     c "-A"      	raw_usagec                    | yt        | t              r| S t        | d      r&t        | j                        r	 | j	                         S t        | d      r&t        | j                        r	 | j                         S 	 t        |       S # t
        $ r Y Iw xY w# t
        $ r Y &w xY w# t
        $ r Y nw xY w	 dt        |       iS # t
        $ r Y yw xY w)an  
    Convert raw provider usage objects to JSON-serializable dicts.

    Handles Pydantic models (OpenAI/Anthropic) and protobuf-like objects (Gemini)
    with a fallback chain to ensure we never pass unserializable objects to PostHog.

    Args:
        raw_usage: Raw usage object from provider SDK

    Returns:
        Plain dict or None if conversion fails
    N
model_dumpto_dict_raw)	
isinstancedicthasattrcallabler0   	Exceptionr1   varsstr)r.   s    r&   serialize_raw_usager:   '   s      )T" y,'HY5I5I,J	''))
 y)$)2C2C)D	$$&&
I  		  		  
I'' sG   B *B ;
B$ 	BB	B! B!$	B0/B04C 	CCtargetsourcemodec                    |dk(  r{|j                  d      }|| j                  d      xs d}||z   | d<   |j                  d      }|| j                  d      xs d}||z   | d<   |j                  d      }|| j                  d      xs d}||z   | d<   |j                  d      }|| j                  d      xs d}||z   | d<   |j                  d      }|| j                  d      xs d}||z   | d<   |j                  d	      }	|	$| j                  d	      xs d}t        ||	      | d	<   |j                  d
      }
|
@t        |
t              r/| j                  d
      }t        |t              r|ni }i ||
| d
<   yyy|dk(  r|j                  d      |d   | d<   |j                  d      |d   | d<   |j                  d      |d   | d<   |j                  d      |d   | d<   |j                  d      |d   | d<   |j                  d	      |d	   | d	<   |j                  d
      	|d
   | d
<   yyt	        d| d      )a  
    Merge streaming usage statistics into target dict, handling None values.

    Supports two modes:
    - "incremental": Add source values to target (for APIs that report new tokens)
    - "cumulative": Replace target with source values (for APIs that report totals)

    Args:
        target: Dictionary to update with usage stats
        source: TokenUsage that may contain None values
        mode: Either "incremental" or "cumulative"
    incrementalinput_tokensNr   output_tokenscache_read_input_tokenscache_creation_input_tokensreasoning_tokensweb_search_countr.   
cumulativezInvalid mode: z'. Must be 'incremental' or 'cumulative')getmaxr3   r4   
ValueError)r;   r<   r=   source_inputcurrentsource_outputsource_cache_readsource_cache_creationsource_reasoningsource_web_searchsource_raw_usagecurrent_raw_valuecurrent_raws                r&   merge_usage_statsrT   W   s    }zz.1#jj05AG%,|%;F>"

?3$jj16QG&-&=F?#"JJ'@A(jj!:;@qG07:K0KF,- &

+H I ,jj!>?D1G4;>S4SF01!::&89'jj!349G)03C)CF%&"JJ'9:(jj!349G),W6G)HF%&
 "::k2'J7G,N &

; 7%/0A4%H!b  #F["E4D"EF; -O' 
	::n%1%+N%;F>"::o&2&,_&=F?#::/0<067P0QF,-::34@4:-5F01 ::()5)/0B)CF%&::()5)/0B)CF%&::k"."("5F; / >$/VWXXr-   kwargsc                 >    i }dD ]  }|| v s| |   | |   ||<    |S )z?
    Extracts model parameters from the kwargs dictionary.
    )
temperature
max_tokensmax_completion_tokenstop_pfrequency_penaltypresence_penaltynstopstream	streamingr#   )rU   model_paramsparams      r&   get_model_paramsrc      s=     L F?ve}8"(-L r-   providerc                     |dk(  rddl m}  ||       S |dk(  rddlm}  ||       S |dk(  rddlm}  ||       S t        dd      S )	z{
    Extract usage statistics from response based on provider.
    Delegates to provider-specific converter functions.
    	anthropicr   )%extract_anthropic_usage_from_responseopenai)"extract_openai_usage_from_responsegemini)"extract_gemini_usage_from_response)r@   rA   )(posthog.ai.anthropic.anthropic_converterrg   "posthog.ai.openai.openai_converterri   "posthog.ai.gemini.gemini_converterrk   r   )responserd   rg   ri   rk   s        r&   	get_usagerp      s_    
 ;	
 5X>>	X		
 2(;;	X		
 2(;;1A66r-   c                 x    |dk(  rddl m}  ||       S |dk(  rddlm}  ||       S |dk(  rddlm}  ||       S g S )z4
    Format a regular (non-streaming) response.
    rf   r   )format_anthropic_responserh   )format_openai_responserj   )format_gemini_response)rl   rr   rm   rs   rn   rt   )ro   rd   rr   rs   rt   s        r&   format_responseru      sK     ;V(22	X	M%h//	X	M%h//Ir-   ro   c                 v    |dk(  rddl m}  ||       S |dk(  rddlm}  ||       S |dk(  rddlm}  ||       S y)	z4Extract stop reason from response based on provider.rh   r   )extract_openai_stop_reasonrf   )extract_anthropic_stop_reasonrj   )extract_gemini_stop_reasonN)rm   rw   rl   rx   rn   ry   )ro   rd   rw   rx   ry   s        r&   extract_stop_reasonrz      sK    8Q)(33	[	 	
 -X66	X	Q)(33r-   c                 v    | dk(  rddl m}  ||      S | dk(  rddlm}  ||      S | dk(  rddlm}  ||      S y)	z>
    Extract available tool calls for the given provider.
    rf   r   )extract_anthropic_toolsrj   )extract_gemini_toolsrh   )extract_openai_toolsN)rl   r|   rn   r}   rm   r~   )rd   rU   r|   r}   r~   s        r&   extract_available_tool_callsr      sI     ;T&v..	X	K#F++	X	K#F++r-   c                    |dk(  r5ddl m} | j                  d      xs g }| j                  d      } |||      S |dk(  r2ddlm} | j                  dg       }| j                  d	      } |||      S |d
k(  r
ddlm} | j                  d      }	| j                  d      }
 ||	|
      }| j                  d      <t        d |D              }|s(t        t        d| j                  d      d      }|g|z   }| j                  d      yt        d t        |      D        d      }|3||   j                  dd      }| d| j                  d       ||   d<   |S t        t        d| j                  d      d      }|g|z   }|S g S )zJ
    Merge system prompts and format messages for the given provider.
    rf   r   )format_anthropic_inputmessagessystemrj   )format_gemini_input_with_systemcontentsconfigrh   )format_openai_inputinputNc              3   D   K   | ]  }|j                  d       dk(    ywroler   NrG   )r$   msgs     r&   r'   z&merge_system_prompt.<locals>.<genexpr>1  s     MHSSWWV_8Hs    )r   contentinstructionsc              3   P   K   | ]  \  }}|j                  d       dk(  s|   ywr   r   )r$   ir   s      r&   r'   z&merge_system_prompt.<locals>.<genexpr>=  s&     T!4vq#88S!4s   &&r    z

)rl   r   rG   rn   r   rm   r   r*   r   r   next	enumerate)rU   rd   r   r   r   r   r   r   r   messages_paraminput_param
has_system
system_msg
system_idxsystem_contentinstruction_msgs                   r&   merge_system_promptr     s    ;S::j)/RH%%h77	X	V::j"-H%.x@@	X	J  J/jj) '~{C ::h+MHMMJ!$%&**X2FG
 '<(2 ::n%1T8!4TJ
 %!)*!5!9!9)R!H%&d6::n+E*FG $Y/  #'$%&**^2LM# ,,x7 Ir-   posthog_distinct_id	ph_clientposthog_trace_idposthog_privacy_modeposthog_groupsbase_urlcall_method.c	                 T   t        j                          }
d}d}d}t               }i }t        |d      5  | rt        |        	  |d.i |	}t        j                          }||
z
  }|t        t        j                               }| duxs t        j                         du}|st        |       |r)t        |d	      s|d
k(  rt        |d      rt        ||      }t        |	|      }t        ||      }t!        d|       t!        d|	j#                  d      xs t        |dd             t!        dt%        |	             t!        dt'        |||             t!        dt'        ||t)        ||                   t!        d|       t!        d|j#                  dd             t!        d|j#                  dd             t!        d|       t!        d|       t!        dt        |             t+        |       t-        ||	      }|rt!        d|       |j#                  d      }||dkD  rt!        d|       |j#                  d      }||dkD  rt!        d|       |j#                  d      }||dkD  rt!        d |       |j#                  d!      }||dkD  rt!        d"|       |j#                  d#      }|t!        d$|       t/        ||      }|t!        d%|       |st!        d&d       |d'k(  r7|	j#                  d(      &t!        d)t'        |||	j#                  d(                   t        |d*      rft1        |j2                        rQt5               }i ||xs i |xs i }t7        ||      |d+<   |j3                  t        j                         d,||-       	 |r|	 ddd       |S # t        $ r-}|}t        |dd      }d|j                         d}Y d}~d}~ww xY w# t        j                          }||
z
  }|t        t        j                               }| duxs t        j                         du}|st        |       |r)t        |d	      s|d
k(  rt        |d      rt        ||      }t        |	|      }t        ||      }t!        d|       t!        d|	j#                  d      xs t        |dd             t!        dt%        |	             t!        dt'        |||             t!        dt'        ||t)        ||                   t!        d|       t!        d|j#                  dd             t!        d|j#                  dd             t!        d|       t!        d|       t!        dt        |             t+        |       t-        ||	      }|rt!        d|       |j#                  d      }||dkD  rt!        d|       |j#                  d      }||dkD  rt!        d|       |j#                  d      }||dkD  rt!        d |       |j#                  d!      }||dkD  rt!        d"|       |j#                  d#      }|t!        d$|       t/        ||      }|t!        d%|       |st!        d&d       |d'k(  r7|	j#                  d(      &t!        d)t'        |||	j#                  d(                   t        |d*      rgt1        |j2                        rQt5               }i ||xs i |xs i }t7        ||      |d+<   |j3                  t        j                         d,||-       w w w xY w# 1 sw Y   |S xY w)/z
    Common usage-tracking logic for both sync and async calls.
    call_method: the llm call method (e.g. openai.chat.completions.create)
    N   Fclientcapture_exceptionsstatus_coder   Tz$ai_is_errorz	$ai_errorusagerj   usage_metadata$ai_provider	$ai_modelmodel$ai_model_parameters	$ai_input$ai_output_choices$ai_http_statusr   r@   r   rA   $ai_latency$ai_trace_id$ai_base_url	$ai_toolsrB   r   rC   r   rD   r   rE   $ai_web_search_countr.   	$ai_usage$ai_stop_reason$process_person_profilerh   r   $ai_instructionscapture$ai_tokens_source$ai_generationdistinct_idevent
propertiesgroupsr#   timer   r   r
   r7   getattr__str__r9   uuiduuid4r   get_context_distinct_idr5   rp   r   sanitize_messagesr   rG   rc   with_privacy_moderu   r   r   rz   r6   r   r	   r,   )r   r   rd   r   r   r   r   r   r   rU   
start_timero   errorhttp_statusr   error_paramsexcend_timelatencyhas_person_distinct_idr   sanitized_messagesavailable_tool_calls
cache_readcache_creation	reasoningrE   r.   stop_reasonr   merged_propertiess                                  r&   call_llm_and_track_usager   U  si     JHEK"E#%L	I%	@01w	",V,H yy{H+G'#&tzz|#4  $4/ B335TA #
 * !12'*(WX?O-P!(H5*68<H!28X!F)VZZ0TGHgt4TU&(8(@A!)-ACUV $!3_Xx5X !;/"EIIna$@A#UYY%BCw' 01H.&x0#?&#Q #K!56#<=J%*q.1:>"YY'DEN)nq.@5~F		"45I$Q*I6$yy);<+0@10D*,<=		+.I$K+-hAK&%{3)-u5 8#

>(B(N&%!#7N9S y),):K:K1L#:%%)/R% $)r%!
 :L0:!"56 !! ( @ @ B*0)	 "  K { 
A@ Ou  	E!]AK !% [[]L	 yy{H+G'#&tzz|#4  $4/ B335TA #
 * !12'*(WX?O-P!(H5*68<H!28X!F)VZZ0TGHgt4TU&(8(@A!)-ACUV $!3_Xx5X !;/"EIIna$@A#UYY%BCw' 01H.&x0#?&#Q #K!56#<=J%*q.1:>"YY'DEN)nq.@5~F		"45I$Q*I6$yy);<+0@10D*,<=		+.I$K+-hAK&%{3)-u5 8#

>(B(N&%!#7N9S y),):K:K1L#:%%)/R% $)r%!
 :L0:!"56 !! ( @ @ B*0)	 "  2M,Y 
A@ OsC   \NM\	O%"OOOOM\\\'call_async_methodc	                 r  K   t        j                          }
d }d }d}t               }i }t        |d      5  | rt        |        	  |d-i |	 d {   }t        j                          }||
z
  }|t        t        j                               }| d uxs t        j                         d u}|st        |       |r)t        |d      s|d	k(  rt        |d
      rt        ||      }t        |	|      }t        ||      }t!        d|       t!        d|	j#                  d      xs t        |dd              t!        dt%        |	             t!        dt'        |||             t!        dt'        ||t)        ||                   t!        d|       t!        d|j#                  dd             t!        d|j#                  dd             t!        d|       t!        d|       t!        dt        |             t+        |       t-        ||	      }|rt!        d|       |j#                  d      }||dkD  rt!        d|       |j#                  d      }||dkD  rt!        d|       |j#                  d      }||dkD  rt!        d|       |j#                  d       }||dkD  rt!        d!|       |j#                  d"      }|t!        d#|       t/        ||      }|t!        d$|       |st!        d%d       |d&k(  r7|	j#                  d'      &t!        d(t'        |||	j#                  d'                   t        |d)      rft1        |j2                        rQt5               }i ||xs i |xs i }t7        ||      |d*<   |j3                  t        j                         d+||,       	 |r|	 d d d        |S 7 V# t        $ r-}|}t        |dd      }d|j                         d}Y d }~d }~ww xY w# t        j                          }||
z
  }|t        t        j                               }| d uxs t        j                         d u}|st        |       |r)t        |d      s|d	k(  rt        |d
      rt        ||      }t        |	|      }t        ||      }t!        d|       t!        d|	j#                  d      xs t        |dd              t!        dt%        |	             t!        dt'        |||             t!        dt'        ||t)        ||                   t!        d|       t!        d|j#                  dd             t!        d|j#                  dd             t!        d|       t!        d|       t!        dt        |             t+        |       t-        ||	      }|rt!        d|       |j#                  d      }||dkD  rt!        d|       |j#                  d      }||dkD  rt!        d|       |j#                  d      }||dkD  rt!        d|       |j#                  d       }||dkD  rt!        d!|       |j#                  d"      }|t!        d#|       t/        ||      }|t!        d$|       |st!        d%d       |d&k(  r7|	j#                  d'      &t!        d(t'        |||	j#                  d'                   t        |d)      rgt1        |j2                        rQt5               }i ||xs i |xs i }t7        ||      |d*<   |j3                  t        j                         d+||,       w w w xY w# 1 sw Y   |S xY ww).Nr   Fr   r   r   Tr   r   rj   r   r   r   r   r   r   r   r   r   r@   r   rA   r   r   r   r   rB   r   rC   r   rD   r   rE   r   r.   r   r   r   rh   r   r   r   r   r   r   r#   r   )r   r   rd   r   r   r   r   r   r   rU   r   ro   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rE   r.   r   r   r   s                                  r&   call_llm_and_track_usage_asyncr     sr     JHEK"E#%L	I%	@01w	.888H yy{H+G'#&tzz|#4  $4/ B335TA #
 * !12'*(WX?O-P!(H5*68<H!28X!F)VZZ0TGHgt4TU&(8(@A!)-ACUV $!3_Xx5X !;/"EIIna$@A#UYY%BCw' 01H.&x0#?&#Q #K!56#<=J%*q.1:>"YY'DEN)nq.@5~F		"45I$Q*I6$yy);<+0@10D*,<=		+.I$K+-hAK&%{3)-u5 8#

>(B(N&%!#7N9S y),):K:K1L#:%%)/R% $)r%!
 :L0:!"56 !! ( @ @ B*0)	 "  K { 
A@ Ow 9 	E!]AK !% [[]L	 yy{H+G'#&tzz|#4  $4/ B335TA #
 * !12'*(WX?O-P!(H5*68<H!28X!F)VZZ0TGHgt4TU&(8(@A!)-ACUV $!3_Xx5X !;/"EIIna$@A#UYY%BCw' 01H.&x0#?&#Q #K!56#<=J%*q.1:>"YY'DEN)nq.@5~F		"45I$Q*I6$yy);<+0@10D*,<=		+.I$K+-hAK&%{3)-u5 8#

>(B(N&%!#7N9S y),):K:K1L#:%%)/R% $)r%!
 :L0:!"56 !! ( @ @ B*0)	 "  2M,Y 
A@ Osf   4\7\*N)N&N)M\*
\7&N))	O2"OO"OO""M\''\**\4/\7datac                     |dk(  rt        |       S |dk(  rt        |       S |dk(  rt        |       S |dk(  rt        |       S | S )zASanitize messages using provider-specific sanitization functions.rf   rh   rj   	langchain)r   r   r   r   )r   rd   s     r&   r   r     sS    ;!$''	X	t$$	X	t$$	[	 !$''Kr-   privacy_modevaluec                 $    | j                   s|ry |S r"   )r   )r   r   r   s      r&   r   r     s    Lr-   
event_datac                 <   |j                  d      xs t        t        j                               }|d   |d   t	        |d         t        | |d   |d         t        | |d   |d         d|d	   j                  d
d      |d	   j                  dd      |d   |t        |d         d|j                  d      xs i }t        |d          |d	   j                  d
d      |d	   j                  dd      d}t        ||j                  d            |d<   t        |d   |d         }|r||d<   |d   dk(  r5|d	   j                  dd      }|d	   j                  dd      }||d<   ||d<   nAg d}|D ]8  }	|d	   j                  |	      }
|
t        |
t              s+|
dkD  s1|
|d|	 <   : |d	   j                  d      }|t        |t              r
|dkD  r||d<   |d	   j                  d      }|||d<   |j                  d       }|||d!<   |d   d"k(  r-|d   j                  d#      t        | |d   |d   d#         |d$<   |j                  d%      d&|d'<   t        | d(      r8| j                  |j                  d%      xs |d)||j                  d*      +       yy),a  
    Unified streaming event capture for all LLM providers.

    This function handles the common logic for capturing streaming events across all providers.
    All provider-specific formatting should be done BEFORE calling this function.

    The function handles:
    - Building PostHog event properties
    - Extracting and adding tools based on provider
    - Applying privacy mode
    - Adding special token fields (cache, reasoning)
    - Provider-specific fields (e.g., OpenAI instructions)
    - Sending the event to PostHog

    Args:
        ph_client: PostHog client instance
        event_data: Standardized streaming event data containing all necessary information
    trace_idrd   r   rU   r   formatted_inputformatted_outputr   usage_statsr@   r   rA   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   rf   rB   rC   r   r   )rB   rC   rD   Nz$ai_rE   r   r.   r   r   r   rh   r   r   r   Fr   r   r   r   r   )rG   r9   r   r   rc   r   r   r,   r   r3   intr5   r   )r   r   r   event_propertiessdk_token_tagsavailable_toolsr   r   optional_token_fieldsfieldr   rE   r.   r   s                 r&   capture_streaming_eventr     sR   , ~~j)>S->H #:.( 0H1E F&~&()

 0~&)*

 &}599.!L'6::?AN!), Jz23'( >>,'-2). z*56 '}599.!L'6::?ANN -?
|4-()
 3:8O (7%
 *,.223LaP
#M2667TVWX:D67>L:;!
 +E}-11%8E Zs%;	38 4w0 + "-0445GH$'-q 3C/0 =)--k:I(1% ../K.9*+ 	:(*x $$^4@/@~&x 00
+, ~~m$,6;23 y)$"}5A"'>>(+	 	 	
 %r-   )r?   )/r   r   typingr   r   r   r   r   r   posthogr	   r
   r   r   r   posthog.ai.gatewayr   posthog.ai.sanitizationr   r   r   r   posthog.ai.typesr   r   r   posthog.clientr   PostHogClient	frozensetr+   r9   r,   r:   rT   rc   rp   ru   rz   r   r   boolr   r   r   r   r   r#   r-   r&   <module>r      s     < < J J 9  N M 2 !	 38n2:4S>2J-3 -8DcN+C -b 9FOYOY *OY25OY	OYdT#s(^ S#X ,7# 7* 76 &#  # &3 S#X &?cN?&)?	
?DW!#WW W sm	W
 !c3h0W W T#s(^,W W #s(#W W 	WtS!#SS S sm	S
 !c3h0S S T#s(^,S S  S)S S 	Sl
C 
3 
3 
 d 3 B
B
"B
r-   