
    i-                     P   S r SSKrSSKrSSKJr  SSKJrJr  SSKJrJ	r	  SSK
JrJr  SSKJrJrJr  SS	KJrJrJr  SS
KJrJr  \R0                  " \5      rSrSr " S S5      r SS\\   S\S\\\ \4      S\	\!   S\"\	\\ \4      \	\   4   4
S jjr#S\SS4S jr$S\S\4S jr%g)z,Client instrumentation for Claude Agent SDK.    N)AsyncGenerator)datetimetimezone)AnyOptional)get_current_run_treetrace   )clear_active_tool_runspost_tool_use_hookpre_tool_use_hook)build_llm_input!extract_usage_from_result_messageflatten_content_blocks)clear_parent_run_treeset_parent_run_treezclaude.conversationzclaude.assistant.turnc                       \ rS rSrSrSS\\   4S jjrS\S\S\	\
\\4      S	\\
\\4      4S
 jrSS jrS\
\\4   S	S4S jrSS jrSrg)TurnLifecycle   zHTrack ongoing model runs so consecutive messages are recorded correctly.Nquery_start_timec                     S U l         Xl        g Ncurrent_runnext_start_time)selfr   s     i/home/james-whalen/.local/lib/python3.13/site-packages/langsmith/integrations/claude_agent_sdk/_client.py__init__TurnLifecycle.__init__   s    *.0@    messageprompthistoryreturnc                    U R                   =(       d    [        R                  " 5       nU R                  (       a4  U R                  R                  5         U R                  R	                  5         [        U/X#US9u  pVX`l        SU l         U$ )z/Begin a new model run, ending any existing one.)
start_timeN)r   timer   endpatch%begin_llm_run_from_assistant_messages)r   r!   r"   r#   startfinal_outputruns          r   start_llm_runTurnLifecycle.start_llm_run    ss     $$3		  """$AIv5
 #r    c                 8    [         R                   " 5       U l        g)z0Mark when the next assistant message will start.N)r'   r   r   s    r   mark_next_startTurnLifecycle.mark_next_start1   s    #yy{r    metricsc                 X   U R                   (       a  U(       d  gU R                   R                  R                  S0 5      R                  S0 5      nUR                  U5         U R                   R	                  5         g! [
         a"  n[        R                  SU 35         SnAgSnAff = f)z.Attach token usage details to the current run.Nmetadatausage_metadataz Failed to update usage metrics: )r   extra
setdefaultupdater)   	Exceptionloggerwarning)r   r4   metaes       r   	add_usageTurnLifecycle.add_usage5   s      W%%00R@KKb
 	G	C""$ 	CNN=aSABB	Cs   "A= =
B)B$$B)c                     U R                   (       a<  U R                   R                  5         U R                   R                  5         SU l         gg)zEnd any open run gracefully.N)r   r(   r)   r1   s    r   closeTurnLifecycle.closeB   s<      """$#D r    r   r   )r$   N)__name__
__module____qualname____firstlineno____doc__r   floatr   r   listdictstrr.   r2   r@   rC   __static_attributes__ r    r   r   r      s~    RA% A$'26tCH~2F	$sCx.	!"+Cc3h CD C$r    r   messagesr"   r#   r&   r$   c                    U (       a  [        U S   5      R                  S:w  a  gU S   n[        USS5      n[        5       nU(       d  g[	        X5      nU  Vs/ s H.  n[        US5      (       d  M  [        UR                  5      SS.PM0     n	nUR                  [        S	[        U5      S
:  a  UOU(       a  US   O0 [        U	5      S
:X  a  U	S   OSU	0U(       a  SSU00O0 U(       a#  [        R                  " U[        R                  S9OSS9n
 U
R                  5         [        US5      (       a  [        UR                  5      SS.OSnX4$ s  snf ! [          a"  n["        R%                  SU 35         SnANZSnAff = f)z2Create a traced model run from assistant messages.AssistantMessage)NNmodelNcontent	assistantrU   rolellmr
   r   r6   ls_model_name)tz)namerun_typeinputsoutputsr8   r&   zFailed to post LLM run: )typerE   getattrr   r   hasattrr   rU   create_childLLM_RUN_NAMElenr   fromtimestampr   utcpostr;   r<   r=   )rP   r"   r#   r&   last_msgrT   parentr^   mr_   llm_runr?   final_contents                r   r*   r*   J   s{    tHRL)226HH|HHgt,E!#FV-F A1i  	L*1995{K   !!Vqv6fQir"7|q0y'6J8=zOU342 ))*F " 	G7 8Y'' +8+;+;<kR 
 !!7&  71!5667s$   E1EE 
FE<<Foptionsc                 N   [        U S5      (       d  gU R                  c  0 U l        SU R                  ;  a  / U R                  S'   SU R                  ;  a  / U R                  S'    SSKJn  U" S[        /S9nU" S[
        /S9nU R                  S   R                  SU5        U R                  S   R                  SU5        [        R                  S5        g! [         a    [        R                  S	5         g[         a"  n[        R                  S
U 35         SnAgSnAff = f)a  Inject LangSmith tracing hooks into ClaudeAgentOptions.

This adds PreToolUse and PostToolUse hooks to capture ALL tool calls
(built-in, external MCP, and SDK MCP). The hooks work across all LLM
providers (Anthropic, Vertex AI, Kimi, etc.) because they use explicit
tool_use_id correlation instead of relying on async context propagation.

Args:
    options: ClaudeAgentOptions instance to modify
hooksN
PreToolUsePostToolUser   )HookMatcher)matcherrp   z8Injected LangSmith tracing hooks into ClaudeAgentOptionsz2Failed to import HookMatcher from claude_agent_sdkz Failed to inject tracing hooks: )rb   rp   claude_agent_sdkrs   r   r   insertr<   debugImportErrorr=   r;   )rn   rs   langsmith_pre_matcherlangsmith_post_matcherr?   s        r   _inject_tracing_hooksr{   y   s    7G$$ }} 7==(&(l# GMM)')m$?0 +DAR@S T!,TBTAU!Vl#**1.CDm$++A/EFOP MKL ?9!=>>?s   &A1C D$9	D$DD$original_classc                      " S SU 5      nU$ )zBWrap ClaudeSDKClient to trace both query() and receive_response().c                      ^  \ rS rSrS\S\4U 4S jjrS\S\S\4U 4S jjrS\\S4   4U 4S jjrSU 4S	 jjr	S\SS4U 4S
 jjr
SrU =r$ )7instrument_claude_client.<locals>.TracedClaudeSDKClient   argskwargsc                    > UR                  S5      =(       d    U(       a  US   OS nU(       a  [        U5        [        TU ]  " U0 UD6  S U l        S U l        g )Nrn   r   )getr{   superr   _prompt_start_time)r   r   r   rn   	__class__s       r   r   @instrument_claude_client.<locals>.TracedClaudeSDKClient.__init__   sJ    jj+J4QTG%g.Gd-f-*.DL04Dr    r$   c                    >#    [         R                   " 5       U l        [        UR                  S5      =(       d    U(       a  US   OS5      U l        [
        TU ]  " U0 UD6I Sh  vN $  N7f)z/Capture prompt and timestamp when query starts.r"   r    N)r'   r   rM   r   r   r   query)r   r   r   r   s      r   r   =instrument_claude_client.<locals>.TracedClaudeSDKClient.query   sP     #yy{Dvzz(3P4QRQDL77777s   A"A,%A*&A,Nc                  >#    [         TU ]  5       n0 n0 nU R                  (       a  U R                  US'   [        U S5      (       Ga  U R                  (       Ga  [        U R                  S5      (       a  U R                  R
                  (       a  U R                  R
                  n[        U[        5      (       a  XBS'   OY[        U[        5      (       aD  UR                  S5      S:X  a+  SUR                  SS5       3nS	U;   a  US
US	    3-  nXRS'   OXBS'   S H?  n[        U R                  U5      (       d  M   [        U R                  U5      nUc  M;  XsU'   MA     [        [        SUUS9 ISh  vN n[        U5        [        U R                  5      n	/ n
 U  Sh  vN n[!        U5      R"                  nUS:X  a6  U	R%                  XR                  U
5      nU(       a  U
R'                  U5        GO9US:X  aI  [        US5      (       a'  U
R'                  [)        UR*                  5      SS.5        U	R-                  5         OUS:X  a  [        US5      (       aI  [/        U5      n[        US5      (       a  UR0                  b  UR0                  US'   U	R3                  U5        [        USS5      [        USS5      [        USS5      [        USS5      [        USS5      S.R5                  5        VVs0 s H  u  nnUc  M  UU_M     nnnU(       a  UR6                  R9                  U5        U7v   GM   GN GNs  snnf 
 UR;                  U
(       a  U
S   OSS9  O%! [<         a    [>        RA                  S 5         Of = fU	RC                  5         [E        5         [G        5         O)! U	RC                  5         [E        5         [G        5         f = fSSS5      ISh  vN    g! , ISh  vN  (       d  f       g= f7f)!z7Intercept message stream and record chain run activity.r"   rn   system_promptsystemr`   presetzpreset: claude_codeappendz	
append: )rT   permission_mode	max_turnsNchain)r\   r]   r^   r6   rS   UserMessagerU   userrW   ResultMessageusagetotal_cost_usd
total_cost	num_turns
session_idduration_msduration_api_msis_error)r   r   r   r   r   rR   )r_   z'Error while tracing Claude Agent stream)$r   receive_responser   rb   rn   r   
isinstancerM   rL   r   ra   r	   TRACE_CHAIN_NAMEr   r   r   r`   rE   r.   r   r   rU   r2   r   r   r@   itemsr6   r:   r(   r;   r<   	exceptionrC   r   r   )r   rP   trace_inputstrace_metadatar   preset_textattrvalr-   tracker	collectedmsgmsg_typerU   r   kvr>   r   s                     r   r   Hinstrument_claude_client.<locals>.TracedClaudeSDKClient.receive_response   s    w/1H ,.LN ||)-X& tY''DLLLDLL/::22$(LL$>$>M!-551>X.#M488(,,V4@"*=+<+<X}+U*V W (  (=8 +M(<S;T/U U5@25B2 FDt||T22%dllD9?3640	 F % #'	 
 #C('(8(8924	5-%- -"c#'9#5#5#'99&-&;&; #\\9'G  ' ) 0 0 9%6&sI66 ) 0 03I#++3V06%&!" $335%8&sG44(I#(N %,C1A$B$B(+(:(:(F:=:L:LE,$7 ' 1 1% 8 29k41P29#|T2R3:3t3T7>(+->8& 18Z0N-" #(%'-*$-*DAq $% !%1-* ! $  $ # 3 3D 9!	q-"<$= &.\ GGYIbMDGI  P$$%NOP MMO)+*, MMO)+*,     s   D4O?;O?O?2L73O?6#O%M M L:!M$EM 5
L=
L=

-M 7O?:M="M N* N?N*NN*%O%*&OO%O?O!O?%O<+O.,O<8O?c                 @   >#    [         TU ]  5       I S h  vN   U $  N7fr   )r   
__aenter__)r   r   s    r   r   Binstrument_claude_client.<locals>.TracedClaudeSDKClient.__aenter__   s!     '$&&&K 's   c                 <   >#    [         TU ]  " U6 I S h  vN   g  N7fr   )r   	__aexit__)r   r   r   s     r   r   Ainstrument_claude_client.<locals>.TracedClaudeSDKClient.__aexit__$  s     '#T***s   )r   r   )r$   TracedClaudeSDKClient)rE   rF   rG   rH   r   r   r   r   r   r   r   rN   __classcell__)r   s   @r   r   r      se    	5# 	5 	5	8S 	8C 	8C 	8g	-N39,E g	-R		+ 	+ 	+ 	+r    r   rO   )r|   r   s     r   instrument_claude_clientr      s    + +B ! r    r   )&rI   loggingr'   collections.abcr   r   r   typingr   r   langsmith.run_helpersr   r	   _hooksr   r   r   	_messagesr   r   r   _toolsr   r   	getLoggerrE   r<   r   rd   r   rK   rL   rM   rJ   tupler*   r{   r   rO   r    r   <module>r      s    2   * '   = Q Q 
 ?			8	$( &.$ .$j #'	,"3i,"," $sCx.!," 	,"
 8DcN#Xc]23,"^'?3 '?4 '?TD!S D!S D!r    