ó
    üÞ jþª  ã                  ó¦  • S r SSKJr  SSKrSSKrSSKrSSKJrJr  SSK	J
r
  SSKJrJrJrJr  SSKJr  SSKJr  SS	KJrJr  SS
KJr  SSKJrJrJr  SSKJrJr  SSK J!r!J"r"J#r#J$r$J%r%J&r&J'r'J(r(J)r)  SSK*J+r+J,r,J-r-  Sr.Sr/Sr0Sr1Sr2SS1r3Sr4SS1r5Sr6Sr7Sr8Sr9Sr:SS S!S"S#.r;S$r<\Rz                  " \>5      r?\S%   r@\A" \" \@5      5      rB " S& S'\5      rCg)(u  OTel â†’ LangSmith bridge for LiveKit Agents.

Rewrites LiveKit's ``lk.*`` span data into the ``gen_ai.*`` / ``langsmith.*``
namespaces LangSmith ingests; non-LiveKit spans on the same provider pass
through untouched.

The root span is held until the processor's AgentSession close hook captures
its session report. LiveKit's recorder supplies audio on that report; egress
audio arrives separately through :meth:`complete_recording`. Shared export /
``thread_id`` / message plumbing lives in :class:`BaseLangSmithSpanProcessor`.
é    )ÚannotationsN)ÚCallableÚMutableMapping)ÚPath)ÚAnyÚLiteralÚOptionalÚget_args)ÚTTLCache)ÚContext)ÚSpanÚSpanProcessor)Úget_package_version)Úbuild_assistant_messageÚbuild_user_messageÚtry_parse_json_object)ÚBaseLangSmithSpanProcessorÚTranslatedSpané   )	Úbuild_message_from_eventÚ build_messages_from_chat_historyÚextract_llm_usageÚextract_model_from_lk_metricsÚ extract_provider_from_lk_metricsÚextract_realtime_usageÚ$flatten_lk_attributes_to_ls_metadataÚis_livekit_spanÚnormalize_provider)Ú_ConversationStateÚ_PendingAudioÚ_PendingThreadStateg      ¬@i † g      >@Ú	user_turnÚllm_requestÚllm_nodeÚllm_request_runÚtts_requestÚtts_nodeÚtts_request_runÚ
agent_turnÚagent_sessionÚfunction_toolÚrealtime_metricsÚuser_speakingÚsystemÚuserÚ	assistantÚtool)zgen_ai.system.messagezgen_ai.user.messagezgen_ai.assistant.messagezgen_ai.tool.messagezgen_ai.choice)Úsession_reportÚegressÚnonec            
      óÚ  ^ • \ rS rSrSr S7SSSSSS\\S.                     S8U 4S jjjjrS9S jrS:S	 jr	      S;S
 jr
S<S jrS=S jrS>U 4S jjrS7S?U 4S jjjrS@S jrSAS jr      SBS jr        SCS jrSDS jrSSSS.           SES jjrSFS jr    SGS jrSHS jrSIS jrSIS jrSIS jrSIS jrSIS jrSJS jrSHS  jrSKS! jrSLS" jr SIS# jr!SMS$ jr"S%S&.     SNS' jjr#      SOS( jr$SPS) jr%SPS* jr&      SQS+ jr'S=S, jr(S@S- jr)S=S. jr*      SRS/ jr+      SSS0 jr,STU 4S1 jjr-SUSVU 4S2 jjjr.SWS3 jr/      SXS4 jr0SIS5 jr1S6r2U =r3$ )YÚLiveKitLangSmithSpanProcessoréR   zIEnriches LiveKit Agents' OTel spans with LangSmith-compatible attributes.Nz	audio/oggr2   )Úapi_keyÚprojectÚendpointÚaudio_path_providerÚaudio_mime_typeÚrecording_modeÚrecording_timeout_secondsÚstate_ttl_secondsc               óî  >^	• Ub  [         R                  " S[        SS9  [        TU ]  " U4UUUS.U
D6  U[
        ;  a  [        S[        [
        5      < 35      eUS::  a  [        S5      eX`l        Xpl	        X€l
        [        R                  " 5       U l        [        R                  " 5       U l        S
U	4S	 jjnU" 5       U l        U" 5       U l        U" 5       U l        U" 5       U l        U" 5       U l        g)a¨  Create the processor.

Args:
    audio_path_provider: Deprecated compatibility parameter. It is ignored.
    audio_mime_type: default MIME type for embedded recordings.
    recording_mode: where recordings come from: ``"session_report"``
        for LiveKit's recorder, ``"egress"`` for bytes supplied with
        :meth:`complete_recording`, or ``"none"`` for report data
        without audio. This is the default for every conversation;
        :meth:`expect_recording` can override one thread to egress.
    recording_timeout_seconds: how long the root waits for required
        session data before it is exported.
    state_ttl_seconds: lifetime for per-conversation state.
Nz.audio_path_provider is deprecated and ignored.é   )Ú
stacklevel)r8   r9   r:   zrecording_mode must be one of r   z3recording_timeout_seconds must be greater than zeroc                 ó    >• [        [        T S9$ )N)ÚmaxsizeÚttl)r   ÚDEFAULT_STATE_MAXSIZE)r?   s   €Úb/var/www/html/gaurav/venv/lib/python3.13/site-packages/langsmith/integrations/livekit/processor.pyÚ_cacheÚ6LiveKitLangSmithSpanProcessor.__init__.<locals>._cache‘   s   ø€ ÜÔ$9Ð?PÑQÐQó    )Úreturnr   )ÚwarningsÚwarnÚDeprecationWarningÚsuperÚ__init__Ú_RECORDING_MODESÚ
ValueErrorÚsortedÚ_audio_mime_typeÚ_recording_modeÚ_recording_timeout_secondsÚ	threadingÚRLockÚ_state_lockÚ_export_lockÚ_state_by_traceÚ_trace_by_threadÚ_thread_state_waiting_for_traceÚ_completed_threadsÚ_transcripts_waiting_for_trace)ÚselfÚdownstream_processorr8   r9   r:   r;   r<   r=   r>   r?   ÚkwargsrH   Ú	__class__s            `  €rG   rP   Ú&LiveKitLangSmithSpanProcessor.__init__U   s  ù€ ð8 Ñ*Ü�MŠMØ@Ü"Øòô 	‰ÒØ ð	
àØØñ		
ð
 ò	
ð Ô!1Ó1ÜØ0´Ô8HÓ1IÑ0LÐMóð ð %¨Ó)ÜÐRÓSÐSØ /ÔØ-ÔØ*CÔ'ô %Ÿ?š?Ó,ˆÔô
 &ŸOšOÓ-ˆÔ÷	Rñ IOËˆÔÙ:@»(ˆÔñ
 ‹Hð 	Ô,ñ >D»XˆÔñ OUËhˆÕ+rJ   c                ó8   • U R                   R                  U5      $ ©N)r[   Úget)r`   Útrace_ids     rG   Ú
_get_stateÚ(LiveKitLangSmithSpanProcessor._get_state£   s   € Ø×#Ñ#×'Ñ'¨Ó1Ð1rJ   c                ó  • U R                  U5      nUb,  U R                  X R                  R                  U5      5        U$ [	        XR
                  S9nU R                  X R                  R                  U5      5        X R                  U'   U$ )N)rh   r=   )ri   Ú_associate_thread_with_stateÚ_thread_id_by_tracerg   r   rU   r[   )r`   rh   Ústates      rG   Ú_get_or_create_stateÚ2LiveKitLangSmithSpanProcessor._get_or_create_state¦   s†   € Ø—‘ Ó)ˆØÑØ×-Ñ-Ø×/Ñ/×3Ñ3°HÓ=ôð ˆLä"Ø×.BÑ.Bñ
ˆð 	×)Ñ)¨%×1IÑ1I×1MÑ1MÈhÓ1WÔXØ).×Ñ˜XÑ&ØˆrJ   c                ó  • Ub  UR                   U:X  a  g UR                   b-  [        R                  SUR                  UR                   U5        g U R	                  U5      nUb  X1La  [        R                  SU5        g X!l         U R
                  R                  US 5        UR                  U R                  U'   U R                  R                  US 5      nU(       a  UR                  R                  U5        U R                  R                  US 5      nUbk  UR                  b  UR                  Ul        UR                  (       a;  UR                  Ul        UR                  Ul        UR                   Ul        SUl        g g g )NzXlangsmith voice: trace %x is already bound to thread %s; ignoring a second thread id %s.zzlangsmith voice: thread id %s is already bound to an active LiveKit trace; recordings require one active trace per thread.T)Ú	thread_idÚloggerÚwarningrh   Ú_get_state_by_threadr^   Úpopr\   r_   Útranscripts_waiting_for_spanÚextendr]   r=   Úrecording_receivedÚpending_audioÚrecording_started_atÚaudio_status)r`   rn   rr   Úexisting_stateÚwaitingÚpendings         rG   rl   Ú:LiveKitLangSmithSpanProcessor._associate_thread_with_stateµ   sY  € ð Ñ §¡°9Ó <ØØ�?‰?Ñ&Ü�N‰Nð2à—‘Ø—‘Øôð à×2Ñ2°9Ó=ˆØÑ%¨.Ò*EÜ�N‰NðQàôð
 à#ŒØ×Ñ×#Ñ# I¨tÔ4Ø+0¯>©>ˆ×Ñ˜iÑ(Ø×5Ñ5×9Ñ9¸)ÀTÓJˆÞØ×.Ñ.×5Ñ5°gÔ>Ø×6Ñ6×:Ñ:¸9ÀdÓKˆØÑØ×%Ñ%Ñ1Ø'.×'=Ñ'=�Ô$Ø×)×)Ø&-×&;Ñ&;�Ô#Ø-4×-IÑ-I�Ô*Ø%,×%9Ñ%9�Ô"Ø+/�Õ(ð	 *ð rJ   c                óÚ   • U R                   R                  U5      nUc  g U R                  R                  U5      nUb  UR                  U:w  a  U R                   R	                  US 5        g U$ rf   )r\   rg   r[   rr   rv   )r`   rr   rh   rn   s       rG   ru   Ú2LiveKitLangSmithSpanProcessor._get_state_by_threadÝ   se   € Ø×(Ñ(×,Ñ,¨YÓ7ˆØÑØØ×$Ñ$×(Ñ(¨Ó2ˆØ‰=˜EŸO™O¨yÓ8Ø×!Ñ!×%Ñ% i°Ô6ØØˆrJ   c                ó4   • XR                   UR                  '   g rf   )r[   rh   ©r`   rn   s     rG   Ú_refresh_stateÚ,LiveKitLangSmithSpanProcessor._refresh_stateç   s   € Ø/4×Ñ˜UŸ^™^Ò,rJ   c                óÜ   >• [         TU ]  X5        U R                     U R                  U5      nUb"  U R	                  X25        U R                  U5        SSS5        g! , (       d  f       g= f)z@Capture a late thread id and merge any pre-trace lifecycle data.N)rO   Ú_remember_thread_idrY   ri   rl   r…   )r`   rh   rr   rn   rc   s       €rG   rˆ   Ú1LiveKitLangSmithSpanProcessor._remember_thread_idê   sU   ø€ ä‰Ñ# HÔ8Ø×ÓØ—O‘O HÓ-ˆEØÑ Ø×1Ñ1°%ÔCØ×#Ñ# EÔ*÷	 ×Öús   �7AÁ
A+c                óâ   >• [         TU ]  X5        UR                  [        :w  a  g U R	                  UR
                  R                  5        g! [         a    [        R                  SSS9   gf = f)zACapture thread context and install the session-report close hook.NzQlangsmith voice: failed installing the automatic LiveKit session-report callback.T©Úexc_info)
rO   Úon_startÚnameÚ_SESSION_SPANÚ_install_session_report_hookÚcontextrh   Ú	Exceptionrs   rt   )r`   ÚspanÚparent_contextrc   s      €rG   r�   Ú&LiveKitLangSmithSpanProcessor.on_startó   sf   ø€ ä‰Ñ˜Ô.Ø�9‰9œÓ%Øð		Ø×-Ñ-¨d¯l©l×.CÑ.CÕDøÜó 	ô �N‰Nð+àð ó ð	ús   §%A ÁA.Á-A.c                óÂ  ^ ^^^^•  SSK Jn  U" SS9mTc  g[        TSS5      mTc   TR                  m[        T5      nT R                     T R                  T5      mTR                  U:X  a
   SSS5        gUTl
        T R                  T5        SSS5        S	UU UUU4S jjn TR                  SU5        g! [         a     gf = f! [
        [        4 a     gf = f! , (       d  f       NT= f! [         af    T R                     T R                  T5      nUTL a(  UR                  U:X  a  SUl
        T R                  U5        SSS5        e ! , (       d  f       e = ff = f)
z>Attach one additive close listener to the active AgentSession.r   )Úget_job_contextNF)ÚrequiredÚ_primary_agent_sessionc                 ó”   >•  TR                  T5      nTR                  UTTS9  g ! [         a    [        R	                  SSS9   g f = f)N©rh   Úexpected_statezGlangsmith voice: failed capturing the automatic LiveKit session report.Tr‹   )Úmake_session_reportÚ_attach_session_report_to_tracer’   rs   rt   )Ú_ÚreportÚjob_ctxr`   Úsessionrn   rh   s     €€€€€rG   Ú_capture_reportÚSLiveKitLangSmithSpanProcessor._install_session_report_hook.<locals>._capture_report  s\   ø€ ð
Ø ×4Ñ4°WÓ=�Ø×4Ñ4Ø X¸eð 5ò øô ó Ü—‘ð&à!ð ó ðús   ƒ"& ¦AÁAÚclose)rŸ   r   rK   ÚNone)Úlivekit.agentsr—   ÚImportErrorÚgetattrÚprimary_sessionÚAttributeErrorÚRuntimeErrorÚidrY   ro   Úreport_hook_session_idr…   Úoncer’   ri   )	r`   rh   r—   Ú
session_idr£   Úcurrentr¡   r¢   rn   s	   ``    @@@rG   r�   Ú:LiveKitLangSmithSpanProcessor._install_session_report_hook  sZ  ü€ ð	Ý6ñ "¨5Ñ1ˆØ‰?ØÜ˜'Ð#;¸TÓBˆØ‰?ðØ!×1Ñ1�ô ˜“[ˆ
Ø×ÓØ×-Ñ-¨hÓ7ˆEØ×+Ñ+¨zÓ9Ø÷ Ðð ,6ˆEÔ(Ø×Ñ Ô&÷ ÷	ó 	ð	Ø�L‰L˜ /Õ2øôG ó 	Ùð	ûô #¤LÐ1ó Ùðú÷ Õûô, ó 	Ø×!Ó!ØŸ/™/¨(Ó3�Ø˜eÒ#¨×(FÑ(FÈ*Ó(TØ59�GÔ2Ø×'Ñ'¨Ô0÷	 "ð
 ÷ "Ô!ð
 úð	úsX   ‡B7 ¨C Á#CÁ7CÂ$C. Â7
CÃCÃCÃCÃ
C+Ã.EÄ?EÅ	EÅ
E	ÅEc                óB   ^ ^• UR                  S5      SU U4S jj5       ng)ut  Subscribe this processor to a LiveKit ``AgentSession``'s events.

A realtime (speech-to-speech) model's user transcript arrives via the
``user_input_transcribed`` session event â€” never on a span â€” so without
this the ``user_speaking`` spans render bare. Call it once after
creating the session to wire the transcript in::

    processor = configure_livekit(...)
    session = AgentSession(llm=...)
    set_thread_id(conversation_id)
    processor.instrument_session(session, conversation_id)

Each final transcript is paired FIFO with the next ``user_speaking`` span
that has no transcript yet (we have no id to match a transcript to its
exact span). No-op for the cascade pipeline, where the transcript already
rides the STT ``user_turn`` span.

Args:
    session: the LiveKit ``AgentSession`` to subscribe to.
    thread_id: the conversation id, matching :func:`set_thread_id`.
Úuser_input_transcribedc                óŠ   >• [        U SS5      (       a0  TR                  [        T5      [        U SS5      =(       d    S5        g g )NÚis_finalFÚ
transcriptÚ )r©   Ú_record_user_transcriptÚstr)Úevr`   rr   s    €€rG   Ú_on_user_input_transcribedÚTLiveKitLangSmithSpanProcessor.instrument_session.<locals>._on_user_input_transcribedJ  s<   ø€ ä�r˜: u×-Ñ-Ø×,Ñ,Ü˜	“N¤G¨B°¸bÓ$A×$GÀRõð .rJ   N)r»   r   rK   r¦   )Úon)r`   r¢   rr   r¼   s   ` ` rG   Úinstrument_sessionÚ0LiveKitLangSmithSpanProcessor.instrument_session3  s!   ù€ ð. 
�‰Ð,Ó	-÷	ó 
.ñ	rJ   c                óT  • [        U5      nU R                     U R                  U5      nUcF  U R                  R	                  U5      (       a
   SSS5        gU R                  US5         SSS5        gUR                  nSSS5        U R                  UWWS9  g! , (       d  f       N = f)uÚ  Attach a LiveKit session report to the held conversation root.

The report supplies chat history in every recording mode. In
``session_report`` mode it also supplies the recording; egress audio is
delivered separately through :meth:`complete_recording`.

Args:
    report: LiveKit's ``SessionReport`` (duck-typed â€” the module never
        imports it, so it stays importable without ``livekit-agents``).
    thread_id: the conversation id, matching :func:`set_thread_id`.
Núsession reportr›   )rº   rY   ru   r^   rg   Ú_warn_missing_conversationrh   rž   )r`   r    rr   Úthreadrn   rh   s         rG   Úattach_session_reportÚ3LiveKitLangSmithSpanProcessor.attach_session_reportQ  s¢   € ô  �Y“ˆØ×ÓØ×-Ñ-¨fÓ5ˆEØ‰}Ø×*Ñ*×.Ñ.¨v×6Ñ6ð ÷ Ðð ×/Ñ/°Ð8HÔIØ÷ Ðð —~‘~ˆH÷ ð 	×,Ñ,Ø˜X°eð 	-ò 	
÷ Õús   ˜6BÁBÁ3BÂ
B'c               ó˜  • U R                      U R                  U5      nXCLd  UR                  (       a
   SSS5        gUR                  S:H  nSSS5        [	        USS5      nU(       a  [        U5      O/ nW(       a  U R                  U5      OSnU R                      U R                  U5      nXCLd  UR                  (       a
   SSS5        gXtl        SUl        UR                  S:X  a  Uu  Ul        Ul	        Ul
        U R                  U5        SSS5        U R                  U5        g! , (       d  f       Nã= f! , (       d  f       N1= f)z@Commit a report to the exact state captured by a lifecycle hook.Nr2   Úchat_history)NNNT)rY   ri   Úreport_receivedr=   r©   r   Ú_audio_from_session_reportÚreport_transcriptrz   r{   r|   r…   Ú_export_conversation_if_ready)	r`   r    rh   rœ   rn   Úread_report_audioÚhistoryÚmessagesÚreport_audios	            rG   rž   Ú=LiveKitLangSmithSpanProcessor._attach_session_report_to_tracep  s+  € ð ×ÓØ—O‘O HÓ-ˆEØÒ*¨e×.C×.CØ÷ Ðð !&× 4Ñ 4Ð8HÑ HÐ÷	 ô ˜& .°$Ó7ˆÞ@GÔ3°GÔ<ÈRˆö !ð ×+Ñ+¨FÔ3à#ð 	ð ×ÓØ—O‘O HÓ-ˆEØÒ*¨e×.C×.CØ÷ Ðð '/Ô#Ø$(ˆEÔ!Ø×#Ñ#Ð'7Ó7ð
 !ñ	ØÔ'ØÔ.ØÔ&à×Ñ Ô&÷ ð 	×*Ñ*¨8Õ4÷7 Õú÷ Õús#   �(D*¾D*Â(D;ÃAD;Ä*
D8Ä;
E	c                óò  • [        U5      nU R                     U R                  U5      nUcc  U R                  R	                  US5        U R
                  R                  U5      nUc
  [        5       nSUl        X@R
                  U'    SSS5        gSUl        UR                  (       a&  UR                  (       d  SUl        SUl        SUl        U R                  U5        SSS5        g! , (       d  f       g= f)zÊMark one conversation as awaiting :meth:`complete_recording`.

This legacy API overrides the processor's default recording mode for
only ``thread_id``. It may be called before LiveKit starts any spans.
Nr3   )rº   rY   ru   r^   rv   r]   rg   r!   r=   rÉ   ry   rz   r{   r|   r…   )r`   rr   rÄ   rn   r   s        rG   Úexpect_recordingÚ.LiveKitLangSmithSpanProcessor.expect_recording•  sÔ   € ô �Y“ˆØ×ÓØ×-Ñ-¨fÓ5ˆEØ‰}Ø×'Ñ'×+Ñ+¨F°DÔ9Ø×>Ñ>×BÑBÀ6ÓJ�Ø‘?Ü1Ó3�GØ)1�Ô&Ø?F×4Ñ4°VÑ<Ø÷ Ðð $,ˆEÔ Ø×$×$¨U×-E×-Eð '+�Ô#Ø-1�Ô*Ø%)�Ô"Ø×Ñ Ô&÷# ×Öús   ˜A/C(ÂAC(Ã(
C6zrecording.ogg)rŽ   Ú	mime_typeÚ
started_atc               ó  • SnSnU(       aR  U R                   b  [        U5      U R                   :”  a  SnO)[        U[        U5      U=(       d    U R                  S9nSn[        U5      nU R                     U R                  U5      n	U	cœ  U R                  R                  U5      (       a  U R                  US5         SSS5        gU R                  R                  U5      n
U
c
  [        5       n
SU
l        Xjl        XZl        Xzl        SU
l        X R                  U'    SSS5        gSU	l        Xil        XYl        Xyl        SU	l        U R%                  U	5        U	R&                  nSSS5        U R)                  W5        g! , (       d  f       N = f)aH  Attach completed egress audio, or ``None`` for a terminal failure.

``data`` contains the completed recording bytes. ``name`` defaults to
``recording.ogg`` and ``mime_type`` defaults to the processor's configured
audio MIME type. ``started_at`` is the epoch time of the recording's first
sample and enables waterfall alignment.
Nr4   Ú	too_large©rŽ   ÚdatarÕ   Ú	recordingr3   T)Úaudio_size_limit_bytesÚlenr    ÚbytesrT   rº   rY   ru   r^   rg   rÃ   r]   r!   r=   rz   r{   r|   ry   r…   rh   rÌ   )r`   rr   rÚ   rŽ   rÕ   rÖ   rz   ÚstatusrÄ   rn   r   rh   s               rG   Úcomplete_recordingÚ0LiveKitLangSmithSpanProcessor.complete_recording¯  sq  € ð  ˆØ &ˆÞà×+Ñ+Ñ7Ü˜“I × ;Ñ ;Ó;à$‘ä -ØÜ˜t›Ø'×@¨4×+@Ñ+@ñ!�ð
 �ä�Y“ˆØ×ÓØ×-Ñ-¨fÓ5ˆEØ‰}Ø×*Ñ*×.Ñ.¨v×6Ñ6Ø×3Ñ3°F¸KÔHØ÷ Ðð ×>Ñ>×BÑBÀ6ÓJ�Ø‘?Ü1Ó3�Gð *2�Ô&Ø(5Ô%Ø/9Ô,Ø'-Ô$Ø-1�Ô*Ø?F×4Ñ4°VÑ<Ø÷% Ðð& $,ˆEÔ Ø"/ÔØ)3Ô&Ø!'ÔØ'+ˆEÔ$Ø×Ñ Ô&Ø—~‘~ˆH÷3 ð4 	×*Ñ*¨8Õ4÷5 Õús   Á5AE=ÃAE=Ä&=E=Å=
Fc                ó2   • [         R                  SUU5        g )Nz}langsmith voice: no active LiveKit trace for thread %s; the %s arrived after export, or the id did not match set_thread_id().)rs   rt   )r`   rr   Údeliverys      rG   rÃ   Ú8LiveKitLangSmithSpanProcessor._warn_missing_conversationì  s   € Ü�‰ðMàØõ		
rJ   c                óÔ   • [        USS 5      n[        USS 5      nUc  S US4$ [        U5      nU R                  U5      u  pEUc  S X54$ [        UR                  UU R
                  S9UU4$ )NÚaudio_recording_pathÚaudio_recording_started_atr4   rÙ   )r©   r   Ú_read_audio_filer    rŽ   rT   )r`   r    Ú
audio_pathrÖ   rÚ   rß   s         rG   rÊ   Ú8LiveKitLangSmithSpanProcessor._audio_from_session_reportô  sŽ   € ô ˜VÐ%;¸TÓBˆ
Ü˜VÐ%AÀ4ÓHˆ
ØÑØ˜ VÐ+Ð+Ü˜*Ó%ˆ
Ø×,Ñ,¨ZÓ8‰ˆØ‰<Ø˜Ð+Ð+äØ—_‘_ØØ×/Ñ/ñð
 Øð
ð 	
rJ   c                óT  • UR                   R                  R                  nUR                   R                  nU[        :X  a  U R                  U5        gU[        :X  a  U R                  U5        gU[        ;   a  UR                  S5        gU[        :X  a  U R                  U5        gU[        ;   a  UR                  S5        gU[        :X  a  U R                  U5        gU[        :X  a  U R!                  U5      $ U["        :X  a  U R%                  U5        gUS:X  a  UR                  S5        gU[&        :X  a  U R)                  U5        gU[*        :X  a  UR                  S5        gUR                   R,                  c,  [/        UR                   5      (       a  U R1                  X5        gg)NÚchainÚeou_detectionÚllmFT)r“   r‘   rh   rŽ   Ú	_STT_SPANÚ_handle_sttÚ_LLM_INFERENCE_SPANÚ_handle_llm_requestÚ_LLM_WRAPPER_SPANSÚset_kindÚ_TTS_INFERENCE_SPANÚ_handle_ttsÚ_TTS_WRAPPER_SPANSÚ
_TURN_SPANÚ_handle_turnÚ_USER_SPEAKING_SPANÚ_handle_user_speakingr�   Ú_handle_session_endÚ
_TOOL_SPANÚ_handle_toolÚ_REALTIME_METRICS_SPANÚparentr   Ú_handle_root)r`   Útspanrh   rŽ   s       rG   Ú	_dispatchÚ'LiveKitLangSmithSpanProcessor._dispatch	  s‘  € Ø—:‘:×%Ñ%×.Ñ.ˆØ�z‰z�‰ˆà”9ÓØ×Ñ˜UÔ#ð4 ð3 Ô(Ó(Ø×$Ñ$ UÔ+ð0 ð/ Ô'Ó'Ø�N‰N˜7Ô#ð, ð+ Ô(Ó(Ø×Ñ˜UÔ#ð( ð' Ô'Ó'Ø�N‰N˜7Ô#ð$ ð# ”ZÓØ×Ñ˜eÔ$ð  ð Ô(Ó(Ø×-Ñ-¨eÓ4Ð4Ø”]Ó"Ø×$Ñ$ UÔ+ð ð �_Ó$Ø�N‰N˜7Ô#ð ð ”ZÓØ×Ñ˜eÔ$ð ð Ô+Ó+Ø�N‰N˜5Ô!ð ð �Z‰Z×ÑÑ&¬?¸5¿:¹:×+FÑ+Fð ×Ñ˜eÔ.ØØrJ   c                óŽ  • UR                   R                  R                  nUR                  S5        U R                     U R                  U5      nSUl        UR                  n/ Ul        / Ul        U R                  U5        S S S 5        W H  nU R                  U5        M     U R                  U5        g ! , (       d  f       N:= f)Nrì   T)r“   r‘   rh   rô   rY   ro   Úsession_endedÚspans_waiting_for_transcriptrw   r…   Ú_exportrÌ   )r`   r  rh   rn   ÚheldÚspeaking_spans         rG   rü   Ú1LiveKitLangSmithSpanProcessor._handle_session_end*  s¡   € Ø—:‘:×%Ñ%×.Ñ.ˆØ�‰�wÔØ×ÓØ×-Ñ-¨hÓ7ˆEØ"&ˆEÔØ×5Ñ5ˆDØ13ˆEÔ.Ø13ˆEÔ.Ø×Ñ Ô&÷ ó "ˆMØ�L‰L˜Ö'ñ "à×*Ñ*¨8Õ4÷ Õús   ¾AB6Â6
Cc                óÂ  • UR                  S5        UR                  UR                  R                  S5      5        UR	                  [        UR                  R                  S5      5      5        UR                  R                  S5      nU(       a?  UR                  [        SU S35      /S9  UR                  [        [        U5      5      /S9  UR                  5         g )	Nrî   úgen_ai.request.modelúgen_ai.provider.nameúlk.user_transcriptzAudio for: "Ú"©Úprompt©Ú
completion)rô   Ú	set_modelÚ
attributesrg   Úset_providerr   Úset_messagesr   r   rº   Úexclude_from_message_view)r`   r  r·   s      rG   rð   Ú)LiveKitLangSmithSpanProcessor._handle_stt8  sÃ   € Ø�‰�uÔØ�‰˜×(Ñ(×,Ñ,Ð-CÓDÔEØ×ÑÜ˜u×/Ñ/×3Ñ3Ð4JÓKÓLô	
ð ×%Ñ%×)Ñ)Ð*>Ó?ˆ
ÞØ×ÑÜ*¨\¸*¸ÀQÐ+GÓHÐIð ñ ð ×ÑÔ+BÄ3ÀzÃ?Ó+SÐ*TÐÑUØ×'Ñ'Õ)rJ   c                ó   • UR                  S5        / n/ nUR                   Hr  nUR                  [        :X  a  UR	                  [        SU5      5        M4  [        R                  UR                  5      =nc  MX  UR	                  [        XT5      5        Mt     UR                  U=(       d    SU=(       d    SS9  [        UR                  R                  S5      5      nUR                  [        U5      5        [        UR                  R                  S5      5      nU(       a  UR                  " S0 UD6  UR                   Vs/ sH1  nUR                  [        :w  d  M  UR                  [        ;  d  M/  UPM3     snUR                  SS& gs  snf )z™``llm_request``: rebuild prompt/completion from the gen_ai.* events.

The translated events are then stripped so the ingester doesn't render
them twice.
rî   r0   N©r  r  zlk.llm_metrics© )rô   ÚeventsrŽ   Ú_LLM_CHOICE_EVENTÚappendr   Ú_LLM_EVENT_ROLESrg   r  r   r  r  r   r   Ú	set_usage)	r`   r  r  r  ÚeventÚroleÚproviderÚusageÚes	            rG   rò   Ú1LiveKitLangSmithSpanProcessor._handle_llm_requestG  sG  € ð 	�‰�uÔàˆØ!#ˆ
Ø—\”\ˆEØ�z‰zÔ.Ó.Ø×!Ñ!Ô":¸;ÈÓ"NÖOÜ*×.Ñ.¨u¯z©zÓ:Ð:�$ÓGØ—‘Ô6°tÓCÖDñ	 "ð
 	×Ñ &§.¨D¸Z×=OÈ4ÐÑPä3Ø×Ñ× Ñ Ð!1Ó2ó
ˆð 	×ÑÔ-¨hÓ7Ô8ä! %×"2Ñ"2×"6Ñ"6Ð7GÓ"HÓIˆÞØ�OŠOÑ$˜eÒ$ð —\’\ó
á!�Ø�v‰vÔ*Ñ*ó à/0¯v©vÔ=MÑ/M÷ Ù!ñ
ˆ�‰‘Q‰ùò 
s   ÅFÅFÅ4Fc                óž  • UR                  S5        UR                  5         UR                  R                  S5      =(       dF    UR                  R                  S5      =(       d$    UR                  R                  S5      =(       d    SnUR	                  [        [        U5      5      /[        SU S35      /S9  UR                  UR                  R                  S	5      =(       d$    [        UR                  R                  S
5      5      5        [        UR                  R                  S
5      5      nUR                  [        U5      5        g )Nrî   zlk.input_textzlk.request.textzlk.textr¸   zGenerated audio for: "r  r  r  zlk.tts_metrics)rô   r  r  rg   r  r   rº   r   r  r   r   r  r   )r`   r  Útextr%  s       rG   rö   Ú)LiveKitLangSmithSpanProcessor._handle_ttsg  s%  € Ø�‰�uÔØ×'Ñ'Ô)ð ×Ñ× Ñ  Ó1÷ Ø×Ñ×#Ñ#Ð$5Ó6÷à×Ñ×#Ñ# IÓ.÷ð ð	 	ð 	×ÑÜ&¤s¨4£yÓ1Ð2Ü/Ð2HÈÈÈaÐ0PÓQÐRð 	ñ 	
ð
 	�‰Ø×Ñ× Ñ Ð!7Ó8÷ UÜ,¨U×-=Ñ-=×-AÑ-AÐBRÓ-SÓTô	
ô 4Ø×Ñ× Ñ Ð!1Ó2ó
ˆð 	×ÑÔ-¨hÓ7Õ8rJ   c                ó  • UR                  SUR                  ;   a  SOS5        UR                  R                  S5      nUR                  R                  S5      nUR                  R                  R
                  nUR                  R                  nU(       a6  [        [        U5      5      nUR                  U/S9  U R                  XFU5        U(       a7  [        [        U5      5      nUR                  U/S9  U R                  XFU5        gg)	zÖRender an ``agent_turn`` and append it to the running transcript.

``llm`` for a realtime model (the turn is the model call, usage stamped
here); ``chain`` for cascade (the STT/LLM/TTS children carry their usage).
úlk.realtime_model_metricsrî   rì   zlk.user_inputzlk.response.textr  r  N)rô   r  rg   r“   r‘   rh   Ú
start_timer   rº   r  Ú_append_transcriptr   )r`   r  Ú
user_inputÚresponserh   ÚstartÚmsgs          rG   rù   Ú*LiveKitLangSmithSpanProcessor._handle_turn  sâ   € ð 	�‰Ø0°E×4DÑ4DÓD‰EÈ'ô	
ð ×%Ñ%×)Ñ)¨/Ó:ˆ
Ø×#Ñ#×'Ñ'Ð(:Ó;ˆØ—:‘:×%Ñ%×.Ñ.ˆØ—
‘
×%Ñ%ˆÞÜ$¤S¨£_Ó5ˆCØ×Ñ s eÐÑ,Ø×#Ñ# H°5Ô9ÞÜ)¬#¨h«-Ó8ˆCØ×Ñ¨3¨%ÐÑ0Ø×#Ñ# H°5Õ9ð rJ   c                óÌ   • U R                      U R                  U5      nUR                  R                  X245        U R	                  U5        SSS5        g! , (       d  f       g= f)zIAppend a message to the transcript the root rolls up, keyed for ordering.N)rY   ro   r·   r   r…   )r`   rh   ÚmessageÚsort_keyrn   s        rG   r/  Ú0LiveKitLangSmithSpanProcessor._append_transcript–  sL   € à×ÓØ×-Ñ-¨hÓ7ˆEØ×Ñ×#Ñ# XÐ$7Ô8Ø×Ñ Ô&÷ ×Öús   �?AÁ
A#c                ó,  • UR                  S5        U R                     U R                  UR                  R                  R
                  5      nUR                  c
   SSS5        g[        UR                  5      nU(       a  UR                  R                  S5      OSnU(       d  UR                  R                  U5        U R                  U5        SSS5        W(       a$  U R                  UW5        U R                  U5        gg! , (       d  f       N:= f)u  Handle a ``user_speaking`` span â€” the realtime user turn.

Deferred (``False``): stamp+export now if the transcript was already
buffered, else hold it until one is fed (or flushed untouched at session
end). Exported as-is (``True``) when there's no thread id to pair against.
rì   NTr   r¸   F)rô   rY   ro   r“   r‘   rh   rr   Úboolrw   rv   r  r   r…   Ú_apply_user_transcriptr  )r`   r  rn   Úhas_transcriptr·   s        rG   rû   Ú3LiveKitLangSmithSpanProcessor._handle_user_speaking�  sÚ   € ð 	�‰�wÔØ×ÓØ×-Ñ-¨e¯j©j×.@Ñ.@×.IÑ.IÓJˆEØ�‰Ñ&Ø÷ Ðô " %×"DÑ"DÓEˆNæ=K�×2Ñ2×6Ñ6°qÔ9ÐQSð ö "Ø×2Ñ2×9Ñ9¸%Ô@Ø×Ñ Ô&÷ ö Ø×'Ñ'¨¨zÔ:Ø�L‰L˜ÔØØ÷ Õús   ž>DÁ%A,DÄ
Dc                ó.  • [        U5      nU R                     U R                  U5      nUcM  U R                  R	                  U5      =(       d    / nUR                  U5        XPR                  U'    SSS5        gUR                  (       a  UR                  R                  S5      OSnUc  UR                  R                  U5        U R                  U5        SSS5        Wb#  U R                  Xb5        U R                  U5        gg! , (       d  f       N5= f)z»Pair a realtime transcript (from ``instrument_session``) with its span.

Applies it to the oldest held ``user_speaking`` span for the thread, or
buffers it if that span hasn't ended yet.
Nr   )rº   rY   ru   r_   rg   r   r  rv   rw   r…   r;  r  )r`   rr   r·   Útidrn   r~   r  s          rG   r¹   Ú5LiveKitLangSmithSpanProcessor._record_user_transcript¶  sò   € ô �)‹nˆØ×ÓØ×-Ñ-¨cÓ2ˆEØ‰}Ø×=Ñ=×AÑAÀ#ÓF×LÈ"�Ø—‘˜zÔ*Ø;B×3Ñ3°CÑ8Ø÷ Ðð ×5×5ð ×2Ñ2×6Ñ6°qÔ9àð ð
 ‰}Ø×2Ñ2×9Ñ9¸*ÔEØ×Ñ Ô&÷ ð ÑØ×'Ñ'¨Ô:Ø�L‰L˜Õð ÷ Õús   ˜ADÁ:ADÄ
Dc                ó  • UR                  S5        U(       an  X!R                  S'   [        U5      nUR                  U/S9  U R	                  UR
                  R                  R                  X1R
                  R                  5        gg)u  Render a fed transcript onto a ``user_speaking`` span as the user's turn.

Unlike the cascade STT ``user_turn`` (which is excluded), this is the only
record of the realtime user's words, so it's shown â€” as a plain ``user``
message. An empty transcript renders no fabricated I/O.
rî   r  r  N)	rô   r  r   r  r/  r“   r‘   rh   r.  )r`   r  r·   r3  s       rG   r;  Ú4LiveKitLangSmithSpanProcessor._apply_user_transcriptÐ  sq   € ð 	�‰�uÔÞØ5?×ÑÐ1Ñ2Ü$ ZÓ0ˆCØ×Ñ s eÐÑ,Ø×#Ñ#Ø—
‘
×"Ñ"×+Ñ+¨S·*±*×2GÑ2Gõð	 rJ   c                ó^  • UR                  S5        UR                  R                  S5      nU(       a  UR                  S[	        U5      5        UR                  R                  S5      nUb  UR                  U5        UR                  R                  S5      nUb  UR                  U5        g g )Nr1   zlk.function_tool.nameÚ	tool_namezlk.function_tool.argumentszlk.function_tool.output)rô   r  rg   Úset_metadatarº   Úset_tool_inputÚset_tool_output)r`   r  rD  ÚargsÚoutputs        rG   rþ   Ú*LiveKitLangSmithSpanProcessor._handle_toolà  s—   € Ø�‰�vÔØ×$Ñ$×(Ñ(Ð)@ÓAˆ	ÞØ×Ñ˜{¬C°	«NÔ;Ø×Ñ×#Ñ#Ð$@ÓAˆØÑØ× Ñ  Ô&Ø×!Ñ!×%Ñ%Ð&?Ó@ˆØÑØ×!Ñ! &Õ)ð rJ   c                ó  • UR                  S5        UR                  S5        UR                  SS5        UR                  SS5        UR                  S[        S5      =(       d    S	5        U R                     U R                  U5      nXl        U R                  U5        UR                  S
:H  =(       a    UR                  S L nS S S 5        W(       a  [        R                  SU5        U R                  U5        g ! , (       d  f       N== f)Nrì   TÚls_modalityÚaudioÚls_integrationÚlivekitÚls_integration_versionzlivekit-agentsr¸   r3   z°langsmith voice: egress trace %x has no thread id; its recording cannot be delivered. Call set_thread_id() before the conversation starts, or choose a different recording mode.)rô   Úset_root_spanrE  r   rY   ro   Úrootr…   r=   rr   rs   rt   rÌ   )r`   r  rh   rn   Úmissing_egress_threads        rG   r  Ú*LiveKitLangSmithSpanProcessor._handle_rootì  sæ   € Ø�‰�wÔØ×Ñ˜DÔ!Ø×Ñ˜=¨'Ô2Ø×ÑÐ+¨YÔ7Ø×ÑØ$Ô':Ð;KÓ'L×'RÐPRô	
ð ×ÓØ×-Ñ-¨hÓ7ˆEØŒJØ×Ñ Ô&à×$Ñ$¨Ñ0×L°U·_±_ÈÐ5Lð "÷	 ö !Ü�N‰Nð@ð ô	ð 	×*Ñ*¨8Õ4÷ Õús   Á7AC;Ã;
D	F©Úforcec               óþ   • U R                      U R                     U R                  XS9nSSS5        Wc
   SSS5        gUu  pEU R                  XE5        SSS5        g! , (       d  f       N9= f! , (       d  f       g= f)zÇExport the deferred root once the required session data is ready.

Every mode waits for the report. Egress additionally waits for
:meth:`complete_recording`. ``force`` skips those gates at shutdown.
rU  N)rZ   rY   Ú_claim_conversation_for_exportÚ_export_completed_conversation)r`   rh   rV  Úclaimedrn   rR  s         rG   rÌ   Ú;LiveKitLangSmithSpanProcessor._export_conversation_if_ready  sm   € ð ×ÓØ×!Ó!Ø×=Ñ=¸hÐ=ÐT�÷ "à‰Ø÷	 Ðð
 "‰KˆEØ×/Ñ/°Ô<÷ Ðß!Õ!ú÷ Õús&   �A.šAªA.¿A.Á
A+	Á'A.Á.
A<c               ó’  • U R                  U5      nUb  UR                  c  g U(       d  UR                  (       d  g U(       + =(       a    U R                  U5      nU(       a(  U R	                  U5      (       d  U R                  U5        g UR                  nU R                  U5        U R                  R                  US 5        UR                  be  SU R                  UR                  '   U R                  R                  UR                  S 5        U R                  R                  UR                  S 5        U R                  U5        X54$ ©NT)ri   rR  r  Ú_expects_session_dataÚ_has_required_session_dataÚ_schedule_release_timeoutÚ_cancel_release_timerr[   rv   rr   r^   r\   r_   Ú_forget_thread_id)r`   rh   rV  rn   Úexpects_session_datarR  s         rG   rX  Ú<LiveKitLangSmithSpanProcessor._claim_conversation_for_export  s  € ð —‘ Ó)ˆØ‰=˜EŸJ™JÑ.ØÞ˜U×0×0ØØ#(œy×N¨T×-GÑ-GÈÓ-NÐÞ¨×(GÑ(GÈ×(NÑ(NØ×*Ñ*¨5Ô1Øà�z‰zˆØ×"Ñ" 5Ô)Ø×Ñ× Ñ  ¨4Ô0Ø�?‰?Ñ&Ø7;ˆD×#Ñ# E§O¡OÑ4Ø×!Ñ!×%Ñ% e§o¡o°tÔ<Ø×/Ñ/×3Ñ3°E·O±OÀTÔJØ×Ñ˜xÔ(Øˆ{ÐrJ   c                ó„   • UR                   S:X  a  UR                  SL$ UR                  SL=(       d    UR                  SL$ )zCWhether this conversation has a viable session-data delivery route.r3   N)r=   rr   r®   r„   s     rG   r^  Ú3LiveKitLangSmithSpanProcessor._expects_session_data+  sA   € à×Ñ 8Ó+à—?‘?¨$Ð.Ð.ð ×+Ñ+°4Ð7×V¸5¿?¹?ÐRVÐ;VÐVrJ   c                ól   • UR                   =(       a"    UR                  S:g  =(       d    UR                  $ )Nr3   )rÉ   r=   ry   r„   s     rG   r_  Ú8LiveKitLangSmithSpanProcessor._has_required_session_data5  s.   € Ø×$Ñ$÷ 
Ø× Ñ  HÑ,×H°×0HÑ0Hð	
rJ   c                óö   • UR                    H  nU R                  U5        M     U R                  X!5        U R                  X!5      nU(       a  U R	                  X!R
                  5        U R                  U5        g rf   )r  r  Ú_render_conversationÚ_attach_pending_audioÚ_stamp_recording_originr{   )r`   rn   rR  r
  Úattacheds        rG   rY  Ú<LiveKitLangSmithSpanProcessor._export_completed_conversation:  sb   € ð #×?Ô?ˆMØ�L‰L˜Ö'ñ @à×!Ñ! $Ô.Ø×-Ñ-¨dÓ:ˆÞØ×(Ñ(¨×/IÑ/IÔJØ�‰�TÕrJ   c                óê   • UR                   b  g [        R                  " U R                  U R                  UR
                  45      nSUl        X!l         U R                  U5        UR                  5         g r]  )	Úrelease_timerrW   ÚTimerrV   Ú_on_recording_timeoutrh   Údaemonr…   r2  ©r`   rn   Útimers      rG   r`  Ú7LiveKitLangSmithSpanProcessor._schedule_release_timeoutE  sa   € Ø×ÑÑ*ØÜ—’Ø×+Ñ+Ø×&Ñ&Ø�^‰^Ðó
ˆð
 ˆŒØ#ÔØ×Ñ˜EÔ"Ø�‰�rJ   c                ój  • U R                      U R                  U5      nUc
   S S S 5        g S Ul        U R                  U5      (       a
   S S S 5        g UR                  (       d  S/O/ nUR
                  S:X  a"  UR                  (       d  UR                  S5        [        R                  SSR                  U5      UR                  U R                  5        UR
                  S:w  a  UR                  c  SUl        U R                  U5        S S S 5        U R!                  USS	9  g ! , (       d  f       N= f)
NrÂ   r3   zegress recordingzulangsmith voice: timed out waiting for %s for thread %s after %.1fs; exporting the trace with available session data.z and r4   ÚtimeoutTrU  )rY   ri   rp  r_  rÉ   r=   ry   r   rs   rt   Újoinrr   rV   rz   r|   r…   rÌ   )r`   rh   rn   Úmissings       rG   rr  Ú3LiveKitLangSmithSpanProcessor._on_recording_timeoutR  s	  € Ø×ÓØ—O‘O HÓ-ˆEØ‰}Ø÷ Ðð #'ˆEÔØ×.Ñ.¨u×5Ñ5Ø÷ Ðð 16×0E×0EÐ'Ñ(È2ˆGØ×#Ñ# xÓ/¸×8P×8PØ—‘Ð1Ô2Ü�N‰NðJà—‘˜WÓ%Ø—‘Ø×/Ñ/ôð ×#Ñ# vÓ-°%×2EÑ2EÑ2MØ%.�Ô"Ø×Ñ Ô&÷' ð( 	×*Ñ*¨8¸4Ð*Ò@÷) Õús   �D$¬D$ÁB8D$Ä$
D2c                óR   • UR                   nS Ul         Ub  UR                  5         g g rf   )rp  Úcancelrt  s      rG   ra  Ú3LiveKitLangSmithSpanProcessor._cancel_release_timeri  s)   € Ø×#Ñ#ˆØ"ˆÔØÑØ�L‰L�Nð rJ   c                ó¬   • UR                   R                  nUb  Uc  gUS-  nUR                  SU5        UR                  S[        X$-
  S-  5      5        g)ul  Stamp where the recording sits on the trace's timeline, and why.

LiveKit's recorder starts inside ``session.start()`` â€” after room
connect and agent setup â€” so the recording's first sample is seconds
later than the root span's start. Without the offset the trace audio
player has to assume they coincide, and playback runs ahead of the
waterfall by that gap.
Ng    eÍÍAÚls_audio_recording_started_atÚ"ls_audio_recording_start_offset_msiè  )r“   r.  rE  Úround)r`   r  rÖ   Úroot_start_nsÚroot_start_ss        rG   rl  Ú5LiveKitLangSmithSpanProcessor._stamp_recording_origino  s_   € ð Ÿ
™
×-Ñ-ˆØÑ Ñ!6Øð
 % sÑ*ˆØ×ÑÐ:¸JÔGØ×ÑØ0Ü�:Ñ,°Ñ4Ó5õ	
rJ   c                óö   • UR                   (       a  UR                  UR                   S9  gUR                  (       d  gUR                  [        UR                  S S9 VVs/ sH  u  p4UPM	     snnS9  gs  snnf )u  Set the conversation transcript as the root's input.

Prefers a session report's chat history â€” it is ordered by the messages'
own timestamps and carries the tool calls â€” and falls back to the
transcript assembled from spans when no report was supplied.
r  Nc                ó   • U S   $ )Nr   r  )r'  s    rG   Ú<lambda>ÚDLiveKitLangSmithSpanProcessor._render_conversation.<locals>.<lambda>—  s   € ÈQÈqÊTrJ   )Úkey)rË   r  r·   rS   )r`   r  rn   rŸ   r3  s        rG   rj  Ú2LiveKitLangSmithSpanProcessor._render_conversationˆ  sl   € ð ×"×"Ø×Ñ e×&=Ñ&=ÐÑ>ØØ××ØØ×ÑÜ&,¨U×-=Ñ-=Á>Ò&RÔSÑ&R™F˜A“CÑ&RÒSð 	ò 	
ùÛSs   Á!A5
c                ó~  >• U R                      U R                     [        U R                  5      n[        U R                  R	                  5       5       H  nU R                  U5        M     SSS5        W H  nU R                  USS9  M     U R                     [        U R                  R	                  5       5      nU R                  R                  5         U R                  R                  5         U R                  R                  5         U R                  R                  5         U R                  R                  5         SSS5        W H'  nUR                   H  nU R                  U5        M     M)     [        TU ]=  5         SSS5        g! , (       d  f       GN&= f! , (       d  f       Nd= f! , (       d  f       g= f)uÓ   Force-export any still-held roots and user_speaking spans, then shut down.

``force_flush`` deliberately does not â€” a still-held root there is
legitimately in progress, not a buffered export waiting to drain.
NTrU  )rZ   rY   Úlistr[   Úvaluesra  rÌ   Úclearr\   r]   r^   r_   r  r  rO   Úshutdown)r`   Ú	trace_idsrn   rh   Ú	remainingr
  rc   s         €rG   r�  Ú&LiveKitLangSmithSpanProcessor.shutdownš  sP  ø€ ð ×ÓØ×!Ó!Ü  ×!5Ñ!5Ó6�	Ü! $×"6Ñ"6×"=Ñ"=Ó"?Ö@�EØ×.Ñ.¨uÖ5ñ A÷ "ó &�Ø×2Ñ2°8À4Ð2ÓHñ &à×!Ó!Ü  ×!5Ñ!5×!<Ñ!<Ó!>Ó?�	Ø×$Ñ$×*Ñ*Ô,Ø×%Ñ%×+Ñ+Ô-Ø×4Ñ4×:Ñ:Ô<Ø×'Ñ'×-Ñ-Ô/Ø×3Ñ3×9Ñ9Ô;÷ "ó #�Ø%*×%GÔ%G�MØ—L‘L Ö/ó &Hñ #ô ‰GÑÔ÷# Ðß!Ö!ú÷ "Õ!ú÷ Õús=   ŽF.›AFÁ,-F.ÂB&FÄ?AF.Æ
F	ÆF.Æ
F+	Æ'F.Æ.
F<c                ó"   >• [         TU ]  U5      $ )uE   Force-flush the downstream â€” deferred root spans are NOT finalized.)rO   Úforce_flush)r`   Útimeout_millisrc   s     €rG   r•  Ú)LiveKitLangSmithSpanProcessor.force_flush³  s   ø€ ä‰wÑ" >Ó2Ð2rJ   c                ór  •  UR                  5       R                  nU R
                  b2  X R
                  :”  a#  [        R	                  SUUU R
                  5        g UR                  5       S4$ ! [         a    [        R	                  SU5         gf = f! [         a    [        R	                  SUSS9   gf = f)	uË  Read a recording from disk, size-checked *before* it is loaded.

Returns ``(bytes, None)`` or ``(None, reason)``. The size is
checked with ``stat()`` first so an oversize recording is never read
into memory. Callers inline the returned bytes â€” the path itself must
never reach the LangSmith client, which rejects filesystem-referencing
attachments unless ``dangerously_allow_filesystem=True``
(see ``_reject_filesystem_attachments`` / GHSA-f4xh-w4cj-qxq8).
z-langsmith voice: no readable recording at %s.)NÚ
unreadableNz^langsmith voice: recording at %s is %d bytes, over the %d-byte limit; skipping the attachment.)NrØ   z4langsmith voice: failed reading the recording at %s.Tr‹   )ÚstatÚst_sizer’   rs   rt   rÜ   Ú
read_bytes)r`   ÚpathÚsizes      rG   rè   Ú.LiveKitLangSmithSpanProcessor._read_audio_file·  sÀ   € ð	&Ø—9‘9“;×&Ñ&ˆDð
 ×'Ñ'Ñ3Ø×2Ñ2Ó2ä�N‰Nð:àØØ×+Ñ+ôð %ð	&Ø—?‘?Ó$ dÐ*Ð*øô! ó 	&Ü�N‰NÐJÈDÔQÙ%ð	&ûô" ó 	&Ü�N‰NØFØØð ñ ñ
 &ð	&ús#   ‚A. ÁB Á. BÂBÂB6Â5B6c                ón  • UR                   nSnUR                  nUb‚  UR                  (       d  SnOnU R                  b&  [	        UR                  5      U R                  :”  a  SnO;U R                  UUR                  UR                  UR                  S9nU(       a  SOSnUb  UR                  SU5        U$ )NFr4   rØ   rÙ   rm  Úls_audio_attach_status)	rz   r|   rÚ   rÜ   rÝ   Ú_attach_audiorŽ   rÕ   rE  )r`   r  rn   r   rm  rß   s         rG   rk  Ú3LiveKitLangSmithSpanProcessor._attach_pending_audioÜ  s¯   € ð ×%Ñ%ˆØˆØ×#Ñ#ˆØÑØ—<—<Ø‘à×+Ñ+Ñ7Ü˜Ÿ™Ó%¨×(CÑ(CÓCà$‘à×-Ñ-ØØ Ÿ™Ø Ÿ™Ø%×/Ñ/ð	 .ð �ö (0™°V�ØÑØ×ÑÐ7¸Ô@ØˆrJ   c                ó  • [        UR                  R                  5       5       H¯  nUR                  S5      (       d  M  UR                  U   nSUR	                  SS5       3n[        U5      nUbC  [        XT5      R                  5        H$  u  pgXaR                  ;  d  M  XqR                  U'   M&     M�  XAR                  ;   a  M¡  X1R                  U'   M±     [        UR                  R                  S5      5      =(       d$    [        UR                  R                  S5      5      nUR                  U5        SUR                  ;   aD  S	UR                  ;  a3  [        UR                  S   5      n	U	(       a  UR                  " S
0 U	D6  gggg)zÚForward ``lk.*`` to ``langsmith.metadata.lk_*`` and normalize the provider.

Scalars pass through; JSON-object blobs are flattened per field. Runs on
every exported span, so it also covers spans no handler classified.
zlk.zlangsmith.metadata.Ú.rŸ   Nr  zgen_ai.systemr-  zlangsmith.usage_metadatar  )r�  r  ÚkeysÚ
startswithÚreplacer   r   Úitemsr   rg   r  r   r"  )
r`   r  rŠ  ÚvalueÚflat_keyÚparsedrŽ   Úvalr%  r&  s
             rG   Ú_pre_exportÚ)LiveKitLangSmithSpanProcessor._pre_exportö  sx  € ô ˜×(Ñ(×-Ñ-Ó/Ö0ˆCØ—>‘> %×(Ñ(ÙØ×$Ñ$ SÑ)ˆEØ,¨S¯[©[¸¸cÓ-BÐ,CÐDˆHÜ*¨5Ó1ˆFØÑ!Ü!EØó"ç‘%“'ò"‘I�Dð ×#3Ñ#3Õ3Ø14×(Ñ(¨Ó.ñ	"ñ
 Ø×+Ñ+Ó+ÙØ).×Ñ˜XÓ&ñ 1ô" &Ø×Ñ× Ñ Ð!7Ó8ó
÷ Gä × 0Ñ 0× 4Ñ 4°_Ó EÓFð 	ð 	×Ñ˜8Ô$ð (¨5×+;Ñ+;Ó;Ø*°%×2BÑ2BÓBä*Ø× Ñ Ð!<Ñ=óˆEö Ø—’Ñ( %Ó(ð ð Cð <rJ   )
rT   r^   rZ   rU   rV   r[   rY   r]   r\   r_   rf   )ra   zOptional[SpanProcessor]r8   úOptional[str]r9   r°  r:   r°  r;   z&Optional[Callable[[], Optional[Path]]]r<   rº   r=   ÚRecordingModer>   Úfloatr?   r²  rb   r   rK   r¦   )rh   ÚintrK   úOptional[_ConversationState])rh   r³  rK   r   )rn   r   rr   r°  rK   r¦   )rr   rº   rK   r´  )rn   r   rK   r¦   )rh   r³  rr   rº   rK   r¦   )r“   r   r”   zOptional[Context]rK   r¦   )rh   r³  rK   r¦   )r¢   r   rr   rº   rK   r¦   )r    r   rr   rº   rK   r¦   )r    r   rh   r³  rœ   r   rK   r¦   )rr   rº   rK   r¦   )rr   rº   rÚ   zOptional[bytes]rŽ   rº   rÕ   r°  rÖ   úOptional[float]rK   r¦   )rr   rº   rã   rº   rK   r¦   )r    r   rK   z>tuple[Optional[_PendingAudio], Optional[float], Optional[str]])r  r   rK   r:  )r  r   rK   r¦   )rh   r³  r6  Údictr7  r   rK   r¦   )rr   rº   r·   rº   rK   r¦   )r  r   r·   rº   rK   r¦   )r  r   rh   r³  rK   r¦   )rh   r³  rV  r:  rK   r¦   )rh   r³  rV  r:  rK   z3Optional[tuple[_ConversationState, TranslatedSpan]])rn   r   rK   r:  )rn   r   rR  r   rK   r¦   )r  r   rÖ   rµ  rK   r¦   )r  r   rn   r   rK   r¦   )rK   r¦   )i0u  )r–  r³  rK   r:  )r�  r   rK   z%tuple[Optional[bytes], Optional[str]])r  r   rn   r   rK   r:  )4Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú!DEFAULT_RECORDING_TIMEOUT_SECONDSÚDEFAULT_STATE_TTL_SECONDSrP   ri   ro   rl   ru   r…   rˆ   r�   r�   r¿   rÅ   rž   rÓ   rà   rÃ   rÊ   r  rü   rð   rò   rö   rù   r/  rû   r¹   r;  rþ   r  rÌ   rX  r^  r_  rY  r`  rr  ra  rl  rj  r�  r•  rè   rk  r®  Ú__static_attributes__Ú__classcell__)rc   s   @rG   r6   r6   R   sì  ø† ÙSð 9=ðLWð "&Ø!%Ø"&ØFJØ*Ø(8Ø+LØ#<ñLWà5ðLWð ð	LWð
 ðLWð  ðLWð DðLWð ðLWð &ðLWð $)ðLWð !ðLWð ðLWð 
÷LWñ LWô\2ôð&0Ø'ð&0Ø4Að&0à	ô&0ôPô5÷+÷ñ ô .ô`ð<
àð
ð ð
ð 
ô	
ð>#5àð#5ð ð	#5ð
 +ð#5ð 
ô#5ôJ'ð> $Ø#'Ø&*ñ;5àð;5ð ð;5ð
 ð;5ð !ð;5ð $ð;5ð 
õ;5ôz
ð
Øð
à	Gô
ô*ôB5ô*ô
ô@9ô0:ô.'ôô2 ô4ô 
*ô5ð2 /4ñ=Øð=Ø'+ð=à	õ=ð ØðØ'+ðà	<ôô.Wô
ð
	Ø'ð	Ø/=ð	à	ô	ôôAô.ð
Ø#ð
Ø1@ð
à	ô
ð2
Ø#ð
Ø,>ð
à	ô
÷$÷23ñ 3ô#&ðJØ#ðØ,>ðà	ô÷4$)ò $)rJ   r6   )Dr»  Ú
__future__r   ÚloggingrW   rL   Úcollections.abcr   r   Úpathlibr   Útypingr   r   r	   r
   Ú
cachetoolsr   Úopentelemetry.contextr   Úopentelemetry.sdk.tracer   r   Ú$langsmith._internal._package_versionr   Ú"langsmith._internal.voice._helpersr   r   r   Ú-langsmith._internal.voice.base_span_processorr   r   Ú_helpersr   r   r   r   r   r   r   r   r   Ú_stater   r    r!   r½  rF   r¼  rï   rñ   ró   rõ   r÷   rø   r�   rý   rÿ   rú   r!  r  Ú	getLoggerr·  rs   r±  Ú	frozensetrQ   r6   r  rJ   rG   Ú<module>rÏ     s	  ðñ
õ #ã Û Û ß 4Ý ß 3Ó 3å Ý )ß 7å D÷ñ ÷
÷

÷ 
õ 
÷ KÑ Jð #Ð ØÐ ð %)Ð !à€	Ø#Ð Ø Ð"3Ð4Ð Ø#Ð Ø Ð"3Ð4Ð Ø€
Ø€Ø€
Ø+Ð Ø%Ð ð &Ø!Ø +Ø!ñ	Ð ð $Ð à	×	Ò	˜8Ó	$€àÐ:Ñ;€Ù™X mÓ4Ó5Ð ôH)Ð$>õ H)rJ   