Ë
    ³Œj`  ã                  ó  — d Z ddlmZ ddlmZ ddlmZ ddlmZm	Z	m
Z
 ddlmZ ddlmZ ddlmZ dd	lmZmZmZ dd
lmZmZ ddlmZmZmZmZmZmZmZm Z  dZ!dZ"dZ#dZ$ddhZ%dZ&ddhZ'dZ(dZ)dZ*dZ+dZ,dddddœZ-d Z. G d!„ d"e«      Z/y#)$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 call recording is attached to the root span, either from
a local file (``audio_path_provider``, dev) or via :meth:`expect_recording` /
:meth:`complete_recording` (LiveKit Egress, production). Shared export /
``thread_id`` / message plumbing lives in :class:`BaseLangSmithSpanProcessor`.
é    )Úannotations)ÚMutableMapping)ÚPath)ÚAnyÚCallableÚOptional)ÚTTLCache)ÚSpanProcessor)Úget_package_version)Úbuild_assistant_messageÚbuild_user_messageÚtry_parse_json_object)ÚBaseLangSmithSpanProcessorÚTranslatedSpané   )Úbuild_message_from_eventÚ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_providerg      ¬@i † Ú	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.choicec                  óH  ‡ — e Zd ZdZ	 d"dddddedœ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d#ˆ fd„Zd$ˆ fd„Zd%d„Zd&d„Zd	dd
œ	 	 	 	 	 	 	 	 	 d'd„Z	d(d„Z
d)d„Zd)d„Zd)d„Zd)d„Zd*d„Zd(d„Zd+d„Zd,d„Zd-d„Zd)d„Zd.d„Zddœd/d„Zd(d„Zd0d„Zd1ˆ fd„Zd2d3ˆ fd„Zd)d„Zd4d „Zd)d!„Zˆ xZS )5ÚLiveKitLangSmithSpanProcessorzIEnriches LiveKit Agents' OTel spans with LangSmith-compatible attributes.Nz	audio/ogg)Úapi_keyÚprojectÚendpointÚaudio_path_providerÚaudio_mime_typeÚstate_ttl_secondsc               ó  •‡— t        ‰
| �  |f|||dœ|¤Ž || _        || _        dˆfd„}	 |	«       | _         |	«       | _         |	«       | _         |	«       | _         |	«       | _         |	«       | _	         |	«       | _
         |	«       | _        y)a„  Create the processor.

        Args:
            audio_path_provider: returns a local recording path to embed on the
                root (dev only); for production use :meth:`expect_recording` /
                :meth:`complete_recording`.
            audio_mime_type: default MIME type for embedded recordings.
            state_ttl_seconds: lifetime for per-conversation state.
        )r,   r-   r.   c                 ó&   •— t        t        ‰ ¬«      S )N)ÚmaxsizeÚttl)r	   ÚDEFAULT_STATE_MAXSIZE)r1   s   €úr/var/www/html/Fitness-lenito-AI-main/venv/lib/python3.12/site-packages/langsmith/integrations/livekit/processor.pyÚ_cachez6LiveKitLangSmithSpanProcessor.__init__.<locals>._cacheg   s   ø€ ÜÔ$9Ð?PÔQÐQó    N)Úreturnr   )ÚsuperÚ__init__r/   Ú_audio_mime_typeÚ_transcript_by_traceÚ_deferred_root_by_traceÚ_ended_session_tracesÚ_threads_awaiting_recordingÚ_pending_audio_by_threadÚ_trace_by_threadÚ_deferred_user_speakingÚ_pending_user_transcripts)ÚselfÚdownstream_processorr,   r-   r.   r/   r0   r1   Úkwargsr8   Ú	__class__s          `  €r7   r<   z&LiveKitLangSmithSpanProcessor.__init__H   s¥   ù€ ô* 	‰ÑØ ð	
àØØñ		
ð
 ò	
ð $7ˆÔ Ø /ˆÔõ	Rñ
 ‹Hð 	Ô!ñ MSËHˆÔ$á@FÃˆÔ"áFLÃhˆÔ(áCIÃ8ˆÔ%á:@»(ˆÔá‹Hð 	Ô$ñ JPËˆÕ&r9   c                óD   •— t         ‰| �  ||«       || j                  |<   y)uI   Also index threadâ†’trace (so ``complete_recording`` can find the trace).N)r;   Ú_remember_thread_idrC   )rF   Útrace_idÚ	thread_idrI   s      €r7   rK   z1LiveKitLangSmithSpanProcessor._remember_thread_id}   s"   ø€ ä‰Ñ# H¨iÔ8Ø+3ˆ×Ñ˜iÒ(r9   c                ó>   ‡ ‡— |j                  d«      dˆ ˆfd„«       }y)u(  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 the
        processor can't see it from spans alone, and the trace ends up with only
        the agent's turns. Call this 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                óv   •— t        | dd«      r+‰j                  t        ‰«      t        | dd«      xs d«       y y )NÚis_finalFÚ
transcriptÚ )ÚgetattrÚ_record_user_transcriptÚstr)ÚevrF   rM   s    €€r7   Ú_on_user_input_transcribedzTLiveKitLangSmithSpanProcessor.instrument_session.<locals>._on_user_input_transcribedœ   s9   ø€ ä�r˜: uÔ-Ø×,Ñ,Ü˜	“N¤G¨B°¸bÓ$AÒ$GÀRõð .r9   N)rW   r   r:   ÚNone)Úon)rF   ÚsessionrM   rX   s   ` ` r7   Úinstrument_sessionz0LiveKitLangSmithSpanProcessor.instrument_session„   s!   ù€ ð0 
�‰Ð,Ó	-õ	ó 
.ñ	r9   c                ó4   — d| j                   t        |«      <   y)zìHold the root span open until :meth:`complete_recording` supplies the audio.

        Call at conversation start (with egress); always pair with a
        ``complete_recording`` call. ``thread_id`` must match ``set_thread_id``.
        TN)rA   rV   )rF   rM   s     r7   Úexpect_recordingz.LiveKitLangSmithSpanProcessor.expect_recording¥   s   € ð <@ˆ×(Ñ(¬¨Y«Ò8r9   zrecording.ogg)ÚnameÚ	mime_typec               ó(  — |r3|t        |«      |xs | j                  dœ| j                  t        |«      <   | j                  j                  t        |«      d«       | j                  j                  t        |«      «      }|�| j                  |«       yy)a  Attach an egress recording and release the held root.

        ``data`` is the recording bytes (embedded as an attachment), or ``None``
        to release without audio. ``thread_id`` must match :meth:`expect_recording`.
        Safe to call before or after the session ends.
        ©r_   Údatar`   N)	Úbytesr=   rB   rV   rA   ÚpoprC   ÚgetÚ_maybe_release)rF   rM   rc   r_   r`   rL   s         r7   Úcomplete_recordingz0LiveKitLangSmithSpanProcessor.complete_recording­   s„   € ñ àÜ˜d›Ø&Ò?¨$×*?Ñ*?ñ=ˆD×)Ñ)¬#¨i«.Ñ9ð
 	×(Ñ(×,Ñ,¬S°«^¸TÔBØ×(Ñ(×,Ñ,¬S°«^Ó<ˆØÐØ×Ñ Õ)ð  r9   c                óÄ  — |j                   j                  j                  }|j                   j                  }|t        k(  r| j                  |«       y|t        k(  r| j                  |«       y|t        v r|j                  d«       y|t        k(  r| j                  |«       y|t        v r|j                  d«       y|t        k(  r| j                  |«       y|t        k(  r| j!                  |«      S |t"        k(  r\|j                  d«       d| j$                  |<   | j'                  | j(                  j+                  |«      «       | j-                  |«       y|dk(  r|j                  d«       y|t.        k(  r| j1                  |«       y|t2        k(  r|j                  d«       y|j                   j4                  €(t7        |j                   «      r| j9                  ||«       yy)NÚchainTÚeou_detectionÚllmF)ÚspanÚcontextrL   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_speakingÚ_SESSION_SPANr@   Ú_flush_user_speakingÚ_thread_id_by_tracerf   rg   Ú
_TOOL_SPANÚ_handle_toolÚ_REALTIME_METRICS_SPANÚparentr   Ú_handle_root)rF   ÚtspanrL   r_   s       r7   Ú	_dispatchz'LiveKitLangSmithSpanProcessor._dispatchÈ   sË  € Ø—:‘:×%Ñ%×.Ñ.ˆØ�z‰z�‰ˆà”9ÒØ×Ñ˜UÔ#ð< ð; Ô(Ò(Ø×$Ñ$ UÔ+ð8 ð7 Ô'Ñ'Ø�N‰N˜7Ô#ð4 ð3 Ô(Ò(Ø×Ñ˜UÔ#ð0 ð/ Ô'Ñ'Ø�N‰N˜7Ô#ð, ð+ ”ZÒØ×Ñ˜eÔ$ð( ð' Ô(Ò(Ø×-Ñ-¨eÓ4Ð4Ø”]Ò"à�N‰N˜7Ô#Ø37ˆD×&Ñ& xÑ0Ø×%Ñ% d×&>Ñ&>×&BÑ&BÀ8Ó&LÔMØ×Ñ Ô)ð ð �_Ò$Ø�N‰N˜7Ô#ð ð ”ZÒØ×Ñ˜eÔ$ð ð Ô+Ò+Ø�N‰N˜5Ô!ð ð �Z‰Z×ÑÐ&¬?¸5¿:¹:Ô+Fð ×Ñ˜e XÔ.ØØr9   c                óÄ  — |j                  d«       |j                  |j                  j                  d«      «       |j	                  t        |j                  j                  d«      «      «       |j                  j                  d«      }|rE|j                  t        d|› d�«      g¬«       |j                  t        t        |«      «      g¬«       |j                  «        y	)
u6   STT (``user_turn``): audio input â†’ transcribed text.rl   úgen_ai.request.modelúgen_ai.provider.nameúlk.user_transcriptzAudio for: "Ú"©Úprompt©Ú
completionN)rt   Ú	set_modelÚ
attributesrf   Úset_providerr   Úset_messagesr   r   rV   Úexclude_from_message_view)rF   r„   rR   s      r7   rp   z)LiveKitLangSmithSpanProcessor._handle_sttï   sÃ   € à�‰�uÔØ�‰˜×(Ñ(×,Ñ,Ð-CÓDÔEØ×ÑÜ˜u×/Ñ/×3Ñ3Ð4JÓKÓLô	
ð ×%Ñ%×)Ñ)Ð*>Ó?ˆ
ÙØ×ÑÜ*¨\¸*¸ÀQÐ+GÓHÐIð ô ð ×ÑÔ+BÄ3ÀzÃ?Ó+SÐ*TÐÔUØ×'Ñ'Õ)r9   c                óì  — |j                  d«       g }g }|j                  D ]n  }|j                  t        k(  r|j	                  t        d|«      «       Œ2t        j                  |j                  «      x}€ŒT|j	                  t        ||«      «       Œp |j                  |xs d|xs d¬«       t        |j                  j                  d«      «      }|j                  t        |«      «       t        |j                  j                  d«      «      }|r |j                  di |¤Ž |j                  D �cg c])  }|j                  t        k7  r|j                  t        vr|‘Œ+ c}|j                  dd yc c}w )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.
        rl   r(   N©rŒ   rŽ   zlk.llm_metrics© )rt   Úeventsr_   Ú_LLM_CHOICE_EVENTÚappendr   Ú_LLM_EVENT_ROLESrf   r’   r   r�   r‘   r   r   Ú	set_usage)	rF   r„   rŒ   rŽ   ÚeventÚroleÚproviderÚusageÚes	            r7   rr   z1LiveKitLangSmithSpanProcessor._handle_llm_requestÿ   sG  € ð 	�‰�uÔàˆØ!#ˆ
Ø—\”\ˆEØ�z‰zÔ.Ò.Ø×!Ñ!Ô":¸;ÈÓ"NÕOÜ*×.Ñ.¨u¯z©zÓ:Ð:�$ÑGØ—‘Ô6°t¸UÓCÕDð	 "ð
 	×Ñ &¢.¨D¸ZÒ=OÈ4ÐÔPä3Ø×Ñ× Ñ Ð!1Ó2ó
ˆð 	×ÑÔ-¨hÓ7Ô8ô " %×"2Ñ"2×"6Ñ"6Ð7GÓ"HÓIˆÙØˆE�O‰OÑ$˜eÒ$ð —\’\ó
á!�Ø�v‰vÔ*Ò*¨q¯v©vÔ=MÑ/Mò Ø!ñ
ˆ�‰‘Q‰ùò 
s   Ä2.E1c                ó|  — |j                  d«       |j                  «        |j                  j                  d«      xs< |j                  j                  d«      xs |j                  j                  d«      xs d}|j	                  t        t        |«      «      gt        d|› d�«      g¬«       |j                  |j                  j                  d	«      xs$ t        |j                  j                  d
«      «      «       t        |j                  j                  d
«      «      }|j                  t        |«      «       y)uB   ``tts_request``: synthesize text â†’ audio (an ``llm`` inference).rl   zlk.input_textzlk.request.textzlk.textrS   zGenerated audio for: "rŠ   r•   r‡   zlk.tts_metricsN)rt   r“   r�   rf   r’   r   rV   r   r�   r   r   r‘   r   )rF   r„   Útextrž   s       r7   rv   z)LiveKitLangSmithSpanProcessor._handle_tts   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Õ8r9   c                ó  — |j                  d|j                  v rdnd«       |j                  j                  d«      }|j                  j                  d«      }|j                  j                  j
                  }|j                  j                  }|r:t        t        |«      «      }|j                  |g¬«       | j                  |||«       |r;t        t        |«      «      }|j                  |g¬«       | j                  |||«       yy)	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_metricsrl   rj   zlk.user_inputzlk.response.textr‹   r�   N)rt   r�   rf   rm   rn   rL   Ú
start_timer   rV   r’   Ú_append_transcriptr   )rF   r„   Ú
user_inputÚresponserL   ÚstartÚmsgs          r7   ry   z*LiveKitLangSmithSpanProcessor._handle_turn9  sæ   € ð 	�‰Ø0°E×4DÑ4DÑD‰EÈ'ô	
ð ×%Ñ%×)Ñ)¨/Ó:ˆ
Ø×#Ñ#×'Ñ'Ð(:Ó;ˆØ—:‘:×%Ñ%×.Ñ.ˆØ—
‘
×%Ñ%ˆÙÜ$¤S¨£_Ó5ˆCØ×Ñ s eÐÔ,Ø×#Ñ# H¨c°5Ô9ÙÜ)¬#¨h«-Ó8ˆCØ×Ñ¨3¨%ÐÔ0Ø×#Ñ# H¨c°5Õ9ð r9   c                ó†   — | j                   j                  |«      xs g }|j                  ||f«       || j                   |<   y)zIAppend a message to the transcript the root rolls up, keyed for ordering.N)r>   rf   r™   )rF   rL   ÚmessageÚsort_keyÚconversations        r7   r¦   z0LiveKitLangSmithSpanProcessor._append_transcriptP  s@   € à×0Ñ0×4Ñ4°XÓ>ÒDÀ"ˆØ×Ñ˜X wÐ/Ô0à.:ˆ×!Ñ! (Ò+r9   c                óö  — |j                  d«       |j                  j                  d«      }|€yt        |«      }| j                  j                  |«      }|rc|j                  d«      }|r|| j                  |<   n| j                  j                  |d«       | j                  ||«       | j                  |«       y| j                  j                  |«      xs g }|j                  |«       || j                  |<   y)u6  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.
        rj   zlangsmith.metadata.thread_idNTr   F)
rt   r�   rf   rV   rE   re   Ú_apply_user_transcriptÚ_exportrD   r™   )rF   r„   ÚthreadÚpendingrR   Úhelds         r7   r{   z3LiveKitLangSmithSpanProcessor._handle_user_speakingY  sà   € ð 	�‰�wÔØ×!Ñ!×%Ñ%Ð&DÓEˆØˆ>ØÜ�V“ˆà×0Ñ0×4Ñ4°VÓ<ˆÙØ Ÿ™ Q›ˆJÙØ9@�×.Ñ.¨vÒ6à×.Ñ.×2Ñ2°6¸4Ô@Ø×'Ñ'¨¨zÔ:Ø�L‰L˜ÔØà×+Ñ+×/Ñ/°Ó7Ò=¸2ˆØ�‰�EÔØ/3ˆ×$Ñ$ VÑ,Ør9   c                ó˜  — t        |«      }| j                  j                  |«      }|rc|j                  d«      }|r|| j                  |<   n| j                  j                  |d«       | j	                  ||«       | j                  |«       y| j                  j                  |«      xs g }|j                  |«       || j                  |<   y)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.
        r   N)rV   rD   rf   re   r°   r±   rE   r™   )rF   rM   rR   Útidr´   r„   r³   s          r7   rU   z5LiveKitLangSmithSpanProcessor._record_user_transcriptv  s²   € ô �)‹nˆØ×+Ñ+×/Ñ/°Ó4ˆÙØ—H‘H˜Q“KˆEÙØ48�×,Ñ,¨SÒ1à×,Ñ,×0Ñ0°°dÔ;Ø×'Ñ'¨¨zÔ:Ø�L‰L˜ÔØØ×0Ñ0×4Ñ4°SÓ9Ò?¸RˆØ�‰�zÔ"Ø.5ˆ×&Ñ& sÒ+r9   c                ó  — |j                  d«       |rs||j                  d<   t        |«      }|j                  |g¬«       | j	                  |j
                  j                  j                  ||j
                  j                  «       yy)u9  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.
        rl   r‰   r‹   N)	rt   r�   r   r’   r¦   rm   rn   rL   r¥   )rF   r„   rR   rª   s       r7   r°   z4LiveKitLangSmithSpanProcessor._apply_user_transcript‹  su   € ð 	�‰�uÔÙØ5?ˆE×ÑÐ1Ñ2Ü$ ZÓ0ˆCØ×Ñ s eÐÔ,Ø×#Ñ#Ø—
‘
×"Ñ"×+Ñ+¨S°%·*±*×2GÑ2Gõð	 r9   c                óÄ   — |€yt        |«      }| j                  j                  |d«      xs g D ]  }| j                  |«       Œ | j                  j                  |d«       y)zJExport held ``user_speaking`` spans untranscribed (no transcript arrived).N)rV   rD   re   r±   rE   )rF   rM   r¶   r„   s       r7   r}   z2LiveKitLangSmithSpanProcessor._flush_user_speaking›  s\   € àÐØÜ�)‹nˆØ×1Ñ1×5Ñ5°c¸4Ó@ÒFÀBÒFˆEØ�L‰L˜Õð Gà×&Ñ&×*Ñ*¨3°Õ5r9   c                óP  — |j                  d«       |j                  j                  d«      }|r|j                  dt	        |«      «       |j                  j                  d«      }|�|j                  |«       |j                  j                  d«      }|�|j                  |«       yy)z@``function_tool``: render as a proper ``tool`` run with its I/O.r)   zlk.function_tool.nameÚ	tool_namezlk.function_tool.argumentsNzlk.function_tool.output)rt   r�   rf   Úset_metadatarV   Úset_tool_inputÚset_tool_output)rF   r„   rº   ÚargsÚoutputs        r7   r€   z*LiveKitLangSmithSpanProcessor._handle_tool¤  s—   € à�‰�vÔØ×$Ñ$×(Ñ(Ð)@ÓAˆ	ÙØ×Ñ˜{¬C°	«NÔ;Ø×Ñ×#Ñ#Ð$@ÓAˆØÐØ× Ñ  Ô&Ø×!Ñ!×%Ñ%Ð&?Ó@ˆØÐØ×!Ñ! &Õ)ð r9   c                ó  — |j                  d«       |j                  d«       |j                  dd«       |j                  dd«       |j                  dt        d«      xs d	«       || j                  |<   | j                  |«       y
)z?Mark the conversation root and defer it until the session ends.rj   TÚls_modalityÚaudioÚls_integrationÚlivekitÚls_integration_versionzlivekit-agentsrS   N)rt   Úset_root_spanr»   r   r?   rg   )rF   r„   rL   s      r7   rƒ   z*LiveKitLangSmithSpanProcessor._handle_root³  s}   € à�‰�wÔØ×Ñ˜DÔ!Ø×Ñ˜=¨'Ô2Ø×ÑÐ+¨YÔ7Ø×ÑØ$Ô':Ð;KÓ'LÒ'RÐPRô	
ð 27ˆ×$Ñ$ XÑ.Ø×Ñ˜HÕ%r9   F©Úforcec               ó¢  — | j                   j                  |«      }|€y| j                  j                  |«      }|s || j                  vry|�|| j                  v ry| j                   j                  |d«       | j                  |«       | j                  |«       |�| j                  ||«       | j                  |«       | j                  |«       y)u  Export the deferred root once the session ended and audio is ready.

        Requires the root seen, the session ended, and no awaited recording.
        ``force`` skips the last two gates â€” the last-resort path at
        :meth:`shutdown` for a root that never completed.
        N)r?   rf   r~   r@   rA   re   Ú_render_conversationÚ_attach_audio_recordingÚ_attach_pending_audior±   Ú_cleanup_trace)rF   rL   rÈ   r„   r²   s        r7   rg   z,LiveKitLangSmithSpanProcessor._maybe_releaseÀ  sÄ   € ð ×,Ñ,×0Ñ0°Ó:ˆØˆ=ØØ×)Ñ)×-Ñ-¨hÓ7ˆÙØ˜t×9Ñ9Ñ9ØØÐ! f°×0PÑ0PÑ&PØà×$Ñ$×(Ñ(¨°4Ô8Ø×!Ñ! %Ô(Ø×$Ñ$ UÔ+ØÐØ×&Ñ& u¨fÔ5Ø�‰�UÔØ×Ñ˜HÕ%r9   c                óî   — | j                   j                  |j                  j                  j                  g «      }|syt        |d„ ¬«      D ��cg c]  \  }}|‘Œ	 }}}|j                  |¬«       yc c}}w )zJSet the whole transcript (ordered by span start_time) as the root's input.Fc                ó   — | d   S )Nr   r–   )r    s    r7   Ú<lambda>zDLiveKitLangSmithSpanProcessor._render_conversation.<locals>.<lambda>Þ  s   € ÀAÀaÂDr9   )Úkeyr‹   T)r>   rf   rm   rn   rL   Úsortedr’   )rF   r„   ÚentriesÚ_rª   Úmessagess         r7   rÊ   z2LiveKitLangSmithSpanProcessor._render_conversationÙ  sk   € à×+Ñ+×/Ñ/°·
±
×0BÑ0B×0KÑ0KÈRÓPˆÙØÜ&,¨W¹.Õ&IÔJÑ&I™F˜A˜s’CÐ&IˆÑJØ×Ñ (ÐÔ+Øùó Ks   ÁA1c                óœ  — | j                   j                  |«      }| j                  j                  |d «       | j	                  |«       | j
                  j                  |d «       |�f| j                  j                  |d «       | j                  j                  |d «       | j                  j                  |d «       | j                  |«       y y ©N)
r~   rf   r>   re   Ú_forget_thread_idr@   rC   rA   rB   r}   )rF   rL   r²   s      r7   rÍ   z,LiveKitLangSmithSpanProcessor._cleanup_traceâ  s­   € à×)Ñ)×-Ñ-¨hÓ7ˆØ×!Ñ!×%Ñ% h°Ô5Ø×Ñ˜xÔ(Ø×"Ñ"×&Ñ& x°Ô6ØÐØ×!Ñ!×%Ñ% f¨dÔ3Ø×,Ñ,×0Ñ0°¸Ô>Ø×)Ñ)×-Ñ-¨f°dÔ;Ø×%Ñ% fÕ-ð	 r9   c                óî   •— t        | j                  «      D ]  }| j                  |d¬«       Œ t        | j                  j	                  «       «      D ]  }| j                  |«       Œ t        ‰| �  «        y)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.
        TrÇ   N)Úlistr?   rg   rD   Úkeysr}   r;   Úshutdown)rF   rL   r²   rI   s      €r7   rÜ   z&LiveKitLangSmithSpanProcessor.shutdownî  se   ø€ ô ˜T×9Ñ9Ö:ˆHØ×Ñ °ÐÕ5ð ;ä˜4×7Ñ7×<Ñ<Ó>Ö?ˆFØ×%Ñ% fÕ-ð @ä‰ÑÕr9   c                ó"   •— t         ‰| �  |«      S )uE   Force-flush the downstream â€” deferred root spans are NOT finalized.)r;   Úforce_flush)rF   Útimeout_millisrI   s     €r7   rÞ   z)LiveKitLangSmithSpanProcessor.force_flushú  s   ø€ ä‰wÑ" >Ó2Ð2r9   c                óö   — | j                   €y| j                  «       }|�|j                  «       sy	 |j                  «       }| j	                  ||j
                  || j                  ¬«       y# t        $ r Y yw xY w)z>Embed audio from the local ``audio_path_provider`` file (dev).Nrb   )r/   ÚexistsÚ
read_bytesÚ	ExceptionÚ_attach_audior_   r=   )rF   r„   Ú
audio_pathÚaudio_bytess       r7   rË   z5LiveKitLangSmithSpanProcessor._attach_audio_recording   s…   € à×#Ñ#Ð+ØØ×-Ñ-Ó/ˆ
ØÐ Z×%6Ñ%6Ô%8Øð	Ø$×/Ñ/Ó1ˆKð 	×ÑØØ—‘ØØ×+Ñ+ð	 	õ 	
øô ò 	Ùð	ús   ²A, Á,	A8Á7A8c                ó    — | j                   j                  |d«      }|r|j                  d«      sy| j                  ||d   |d   |d   ¬«       y)zCEmbed a recording supplied via :meth:`complete_recording` (egress).Nrc   r_   r`   rb   )rB   re   rf   rä   )rF   r„   r²   r³   s       r7   rÌ   z3LiveKitLangSmithSpanProcessor._attach_pending_audio  sW   € à×/Ñ/×3Ñ3°F¸DÓAˆÙ˜gŸk™k¨&Ô1ØØ×ÑØØ˜‘Ø˜‘Ø˜kÑ*ð	 	õ 	
r9   c                óä  — t        |j                  j                  «       «      D ]¤  }|j                  d«      sŒ|j                  |   }d|j	                  dd«      › �}t        |«      }|�At        ||«      j                  «       D ]#  \  }}||j                  vsŒ||j                  |<   Œ% Œ‡||j                  v rŒ–||j                  |<   Œ¦ t        |j                  j                  d«      «      xs$ t        |j                  j                  d«      «      }|j                  |«       d|j                  v r=d	|j                  vr.t        |j                  d   «      }	|	r |j                  d
i |	¤Ž yyyy)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�   rÛ   Ú
startswithÚreplacer   r   Úitemsr   rf   r‘   r   r›   )
rF   r„   rÑ   ÚvalueÚflat_keyÚparsedr_   Úvalrž   rŸ   s
             r7   Ú_pre_exportz)LiveKitLangSmithSpanProcessor._pre_export  sƒ  € ô ˜×(Ñ(×-Ñ-Ó/Ö0ˆCØ—>‘> %Ô(ØØ×$Ñ$ SÑ)ˆEØ,¨S¯[©[¸¸cÓ-BÐ,CÐDˆHÜ*¨5Ó1ˆFØÐ!Ü!EØ˜Hó"ç‘%“'ò"‘I�D˜#ð  5×#3Ñ#3Ò3Ø14˜×(Ñ(¨Ò.ð	"ð
 Ø˜5×+Ñ+Ñ+ØØ).ˆE×Ñ˜XÒ&ð 1ô$ &Ø×Ñ× Ñ Ð!7Ó8ó
ò Gä × 0Ñ 0× 4Ñ 4°_Ó EÓFð 	ð 	×Ñ˜8Ô$ð
 (¨5×+;Ñ+;Ñ;Ø*°%×2BÑ2BÑBä*Ø× Ñ Ð!<Ñ=óˆEñ Ø�—‘Ñ( %Ó(ð ð Cð <r9   r×   )rG   zOptional[SpanProcessor]r,   úOptional[str]r-   rò   r.   rò   r/   z&Optional[Callable[[], Optional[Path]]]r0   rV   r1   ÚfloatrH   r   r:   rY   )rL   ÚintrM   rV   r:   rY   )r[   r   rM   rV   r:   rY   )rM   rV   r:   rY   )
rM   rV   rc   zOptional[bytes]r_   rV   r`   rò   r:   rY   )r„   r   r:   Úbool)r„   r   r:   rY   )rL   rô   r¬   Údictr­   r   r:   rY   )rM   rV   rR   rV   r:   rY   )r„   r   rR   rV   r:   rY   )rM   rò   r:   rY   )r„   r   rL   rô   r:   rY   )rL   rô   rÈ   rõ   r:   rY   )rL   rô   r:   rY   )r:   rY   )i0u  )rß   rô   r:   rõ   )r„   r   r²   rV   r:   rY   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚDEFAULT_STATE_TTL_SECONDSr<   rK   r\   r^   rh   r…   rp   rr   rv   ry   r¦   r{   rU   r°   r}   r€   rƒ   rg   rÊ   rÍ   rÜ   rÞ   rË   rÌ   rñ   Ú__classcell__)rI   s   @r7   r+   r+   E   sH  ø„ ÙSð 9=ð3Rð "&Ø!%Ø"&ØFJØ*Ø#<ñ3Rà5ð3Rð ð	3Rð
 ð3Rð  ð3Rð Dð3Rð ð3Rð !ð3Rð ð3Rð 
õ3Rõj4óóB@ð $Ø#'ñ*àð*ð ð*ð
 ð*ð !ð*ð 
ó*ó6#óN*ó 
óB9ó2:ó.;óó:6ó*ó 6ó*ó&ð >Cõ &ó2ó
.õ
ö3ó
ó$

÷')r9   r+   N)0rú   Ú
__future__r   Úcollections.abcr   Úpathlibr   Útypingr   r   r   Ú
cachetoolsr	   Úopentelemetry.sdk.tracer
   Ú$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û   r6   ro   rq   rs   ru   rw   rx   r|   r   r�   rz   rš   r˜   r+   r–   r9   r7   Ú<module>r     sÃ   ðñõ #å *Ý ß *Ñ *å Ý 1å D÷ñ ÷
÷
	÷ 	ó 	ð #Ð ØÐ ð €	Ø#Ð Ø Ð"3Ð4Ð Ø#Ð Ø Ð"3Ð4Ð Ø€
Ø€Ø€
Ø+Ð Ø%Ð ð
 &Ø!Ø +Ø!ñ	Ð ð $Ð ô@)Ð$>õ @)r9   