§
    ~Štj`  ã                  ó  — 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/d#S )$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                  ó  ‡ — e Zd ZdZ	 dEdddddedœdFˆ fd„ZdGˆ fd„ZdHd„ZdId„ZdddœdJd#„Z	dKd'„Z
dLd(„ZdLd)„ZdLd*„ZdLd+„ZdMd/„ZdKd0„ZdNd2„ZdOd3„ZdPd4„ZdLd5„ZdQd6„Zd7d8œdRd:„ZdKd;„ZdSd<„ZdTˆ fd=„ZdUdVˆ fd@„ZdLdA„ZdWdC„ZdLdD„Zˆ xZS )XÚLiveKitLangSmithSpanProcessorzIEnriches LiveKit Agents' OTel spans with LangSmith-compatible attributes.Nz	audio/ogg)Úapi_keyÚprojectÚendpointÚaudio_path_providerÚaudio_mime_typeÚstate_ttl_secondsÚdownstream_processorúOptional[SpanProcessor]r,   úOptional[str]r-   r.   r/   ú&Optional[Callable[[], Optional[Path]]]r0   Ústrr1   ÚfloatÚkwargsr   ÚreturnÚNonec               ó^  •‡—  t          ¦   «         j        |f|||dœ|¤Ž || _        || _        dˆfd„}	 |	¦   «         | _         |	¦   «         | _         |	¦   «         | _         |	¦   «         | _         |	¦   «         | _         |	¦   «         | _	         |	¦   «         | _
         |	¦   «         | _        dS )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.   r9   r   c                 ó0   •— t          t          ‰ ¬¦  «        S )N)ÚmaxsizeÚttl)r	   ÚDEFAULT_STATE_MAXSIZE)r1   s   €úf/var/www/html/CA-Chatbot/venv/lib/python3.11/site-packages/langsmith/integrations/livekit/processor.pyÚ_cachez6LiveKitLangSmithSpanProcessor.__init__.<locals>._cacheg   s   ø€ ÝÕ$9Ð?PÐQÑQÔQÐQó    N)r9   r   )Ú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)Úselfr2   r,   r-   r.   r/   r0   r1   r8   rA   Ú	__class__s          `  €r@   rD   z&LiveKitLangSmithSpanProcessor.__init__H   sý   øø€ ð* 	�‰ŒÔØ ð	
àØØð		
ð 	
ð
 ð	
ð 	
ð 	
ð $7ˆÔ Ø /ˆÔð	Rð 	Rð 	Rð 	Rð 	Rð 	Rð
 ˆF‰HŒHð 	Ô!ð MSÈFÉHÌHˆÔ$à@FÀÁÄˆÔ"àFLÀfÁhÄhˆÔ(àCIÀ6Á8Ä8ˆÔ%à:@¸&¹(¼(ˆÔàˆF‰HŒHð 	Ô$ð JPÈÉÌˆÔ&Ð&Ð&rB   Útrace_idÚintÚ	thread_idc                ó`   •— t          ¦   «                              ||¦  «         || j        |<   dS )uI   Also index threadâ†’trace (so ``complete_recording`` can find the trace).N)rC   Ú_remember_thread_idrK   )rN   rP   rR   rO   s      €r@   rT   z1LiveKitLangSmithSpanProcessor._remember_thread_id}   s0   ø€ å‰Œ×#Ò# H¨iÑ8Ô8Ð8Ø+3ˆÔ˜iÑ(Ð(Ð(rB   Úsessionc                óN   ‡ ‡— |                      d¦  «        dˆ ˆfd„¦   «         }dS )	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_transcribedÚevr   r9   r:   c                ó–   •— t          | dd¦  «        r6‰                     t          ‰¦  «        t          | dd¦  «        pd¦  «         d S d S )NÚis_finalFÚ
transcriptÚ )ÚgetattrÚ_record_user_transcriptr6   )rX   rN   rR   s    €€r@   Ú_on_user_input_transcribedzTLiveKitLangSmithSpanProcessor.instrument_session.<locals>._on_user_input_transcribedœ   s_   ø€ å�r˜: uÑ-Ô-ð Ø×,Ò,Ý˜	‘N”N¥G¨B°¸bÑ$AÔ$AÐ$GÀRñô ð ð ð ðð rB   N)rX   r   r9   r:   )Úon)rN   rU   rR   r_   s   ` ` r@   Úinstrument_sessionz0LiveKitLangSmithSpanProcessor.instrument_session„   sK   øø€ ð0 
�ŠÐ,Ñ	-Ô	-ð	ð 	ð 	ð 	ð 	ð 	ñ 
.Ô	-ð	ð 	ð 	rB   c                ó4   — d| j         t          |¦  «        <   dS )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)rI   r6   )rN   rR   s     r@   Úexpect_recordingz.LiveKitLangSmithSpanProcessor.expect_recording¥   s   € ð <@ˆÔ(­¨Y©¬Ñ8Ð8Ð8rB   zrecording.ogg)ÚnameÚ	mime_typeÚdataúOptional[bytes]rd   re   c               ó8  — |r/|t          |¦  «        |p| j        dœ| j        t          |¦  «        <   | j                             t          |¦  «        d¦  «         | j                             t          |¦  «        ¦  «        }|�|                      |¦  «         dS dS )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.
        ©rd   rf   re   N)	ÚbytesrE   rJ   r6   rI   ÚpoprK   ÚgetÚ_maybe_release)rN   rR   rf   rd   re   rP   s         r@   Úcomplete_recordingz0LiveKitLangSmithSpanProcessor.complete_recording­   s¢   € ð ð 	àÝ˜d™œØ&Ð?¨$Ô*?ð=ð =ˆDÔ)­#¨i©.¬.Ñ9ð
 	Ô(×,Ò,­S°©^¬^¸TÑBÔBÐBØÔ(×,Ò,­S°©^¬^Ñ<Ô<ˆØÐØ×Ò Ñ)Ô)Ð)Ð)Ð)ð  ÐrB   Útspanr   Úboolc                ó  — |j         j        j        }|j         j        }|t          k    r|                      |¦  «         �nÉ|t          k    r|                      |¦  «         �n§|t          v r| 	                    d¦  «         �n‡|t          k    r|                      |¦  «         �ne|t          v r| 	                    d¦  «         �nE|t          k    r|                      |¦  «         �n#|t          k    r|                      |¦  «        S |t"          k    rb| 	                    d¦  «         d| j        |<   |                      | j                             |¦  «        ¦  «         |                      |¦  «         n–|dk    r| 	                    d¦  «         nz|t.          k    r|                      |¦  «         nY|t2          k    r| 	                    d¦  «         n8|j         j        €,t7          |j         ¦  «        r|                      ||¦  «         dS dS )NÚchainTÚeou_detectionÚllmF)ÚspanÚcontextrP   rd   Ú	_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_SPANrH   Ú_flush_user_speakingÚ_thread_id_by_tracerl   rm   Ú
_TOOL_SPANÚ_handle_toolÚ_REALTIME_METRICS_SPANÚparentr   Ú_handle_root)rN   ro   rP   rd   s       r@   Ú	_dispatchz'LiveKitLangSmithSpanProcessor._dispatchÈ   s	  € Ø”:Ô%Ô.ˆØŒzŒˆà•9ÒÐØ×Ò˜UÑ#Ô#Ð#Ñ#ØÕ(Ò(Ð(Ø×$Ò$ UÑ+Ô+Ð+Ñ+ØÕ'Ð'Ð'Ø�NŠN˜7Ñ#Ô#Ð#Ñ#ØÕ(Ò(Ð(Ø×Ò˜UÑ#Ô#Ð#Ñ#ØÕ'Ð'Ð'Ø�NŠN˜7Ñ#Ô#Ð#Ñ#Ø•ZÒÐØ×Ò˜eÑ$Ô$Ð$Ñ$ØÕ(Ò(Ð(Ø×-Ò-¨eÑ4Ô4Ð4Ø•]Ò"Ð"à�NŠN˜7Ñ#Ô#Ð#Ø37ˆDÔ& xÑ0Ø×%Ò% dÔ&>×&BÒ&BÀ8Ñ&LÔ&LÑMÔMÐMØ×Ò Ñ)Ô)Ð)Ð)Ø�_Ò$Ð$Ø�NŠN˜7Ñ#Ô#Ð#Ð#Ø•ZÒÐØ×Ò˜eÑ$Ô$Ð$Ð$ØÕ+Ò+Ð+Ø�NŠN˜5Ñ!Ô!Ð!Ð!ØŒZÔÐ&­?¸5¼:Ñ+FÔ+FÐ&ð ×Ò˜e XÑ.Ô.Ð.Ø�5ØˆtrB   c                ó  — |                      d¦  «         |                     |j                             d¦  «        ¦  «         |                     t          |j                             d¦  «        ¦  «        ¦  «         |j                             d¦  «        }|rY|                     t          d|› d�¦  «        g¬¦  «         |                     t          t          |¦  «        ¦  «        g¬¦  «         | 
                    ¦   «          d	S )
u6   STT (``user_turn``): audio input â†’ transcribed text.rt   úgen_ai.request.modelúgen_ai.provider.nameúlk.user_transcriptzAudio for: "ú"©Úprompt©Ú
completionN)r|   Ú	set_modelÚ
attributesrl   Úset_providerr   Úset_messagesr   r   r6   Úexclude_from_message_view)rN   ro   r[   s      r@   rx   z)LiveKitLangSmithSpanProcessor._handle_sttï   s	  € à�Š�uÑÔÐØ�Š˜Ô(×,Ò,Ð-CÑDÔDÑEÔEÐEØ×ÒÝ˜uÔ/×3Ò3Ð4JÑKÔKÑLÔLñ	
ô 	
ð 	
ð Ô%×)Ò)Ð*>Ñ?Ô?ˆ
Øð 	VØ×ÒÝ*Ð+G¸*Ð+GÐ+GÐ+GÑHÔHÐIð ñ ô ð ð ×ÒÕ+BÅ3ÀzÁ?Ä?Ñ+SÔ+SÐ*TÐÑUÔUÐUØ×'Ò'Ñ)Ô)Ð)Ð)Ð)rB   c                ó¦  — |                      d¦  «         g }g }|j        D ]z}|j        t          k    r$|                     t          d|¦  «        ¦  «         Œ6t                               |j        ¦  «        x}�#|                     t          ||¦  «        ¦  «         Œ{|                     |pd|pd¬¦  «         t          |j
                             d¦  «        ¦  «        }|                     t          |¦  «        ¦  «         t          |j
                             d¦  «        ¦  «        }|r |j        di |¤Ž d„ |j        D ¦   «         |j        dd…<   dS )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.
        rt   r(   N©r“   r•   zlk.llm_metricsc                óN   — g | ]"}|j         t          k    ¯|j         t          v¯ |‘Œ#S © )rd   Ú_LLM_CHOICE_EVENTÚ_LLM_EVENT_ROLES)Ú.0Úes     r@   ú
<listcomp>zELiveKitLangSmithSpanProcessor._handle_llm_request.<locals>.<listcomp>  s=   € ð 
ð 
ð 
àØŒvÕ*Ò*Ð*¨q¬vÕ=MÐ/MÐ/Mð à/MÐ/MÐ/MrB   rž   )r|   Úeventsrd   rŸ   Úappendr   r    rl   r™   r   r—   r˜   r   r   Ú	set_usage)rN   ro   r“   r•   ÚeventÚroleÚproviderÚusages           r@   rz   z1LiveKitLangSmithSpanProcessor._handle_llm_requestÿ   sp  € ð 	�Š�uÑÔÐàˆØ!#ˆ
Ø”\ð 	Eð 	EˆEØŒzÕ.Ò.Ð.Ø×!Ò!Õ":¸;ÈÑ"NÔ"NÑOÔOÐOÐOÝ*×.Ò.¨u¬zÑ:Ô:Ð:�$ÐGØ—’Õ6°t¸UÑCÔCÑDÔDÐDøØ×Ò & .¨D¸ZÐ=OÈ4ÐÑPÔPÐPå3ØÔ× Ò Ð!1Ñ2Ô2ñ
ô 
ˆð 	×ÒÕ-¨hÑ7Ô7Ñ8Ô8Ð8õ " %Ô"2×"6Ò"6Ð7GÑ"HÔ"HÑIÔIˆØð 	%ØˆEŒOÐ$Ð$˜eÐ$Ð$Ð$ð
ð 
à”\ð
ñ 
ô 
ˆŒ�Q�Q�Q‰ˆˆrB   c                óº  — |                      d¦  «         |                     ¦   «          |j                             d¦  «        p5|j                             d¦  «        p|j                             d¦  «        pd}|                     t          t          |¦  «        ¦  «        gt          d|› d�¦  «        g¬¦  «         |                     |j                             d	¦  «        p&t          |j                             d
¦  «        ¦  «        ¦  «         t          |j                             d
¦  «        ¦  «        }|                     t          |¦  «        ¦  «         dS )uB   ``tts_request``: synthesize text â†’ audio (an ``llm`` inference).rt   zlk.input_textzlk.request.textzlk.textr\   zGenerated audio for: "r‘   rœ   rŽ   zlk.tts_metricsN)r|   rš   r—   rl   r™   r   r6   r   r–   r   r   r˜   r   )rN   ro   Útextr©   s       r@   r~   z)LiveKitLangSmithSpanProcessor._handle_tts   sf  € à�Š�uÑÔÐØ×'Ò'Ñ)Ô)Ð)ð Ô× Ò  Ñ1Ô1ð ØÔ×#Ò#Ð$5Ñ6Ô6ðàÔ×#Ò# IÑ.Ô.ðð ð	 	ð 	×ÒÝ&¥s¨4¡y¤yÑ1Ô1Ð2Ý/Ð0PÈÐ0PÐ0PÐ0PÑQÔQÐRð 	ñ 	
ô 	
ð 	
ð
 	�ŠØÔ× Ò Ð!7Ñ8Ô8ð UÝ,¨UÔ-=×-AÒ-AÐBRÑ-SÔ-SÑTÔTñ	
ô 	
ð 	
õ 4ØÔ× Ò Ð!1Ñ2Ô2ñ
ô 
ˆð 	×ÒÕ-¨hÑ7Ô7Ñ8Ô8Ð8Ð8Ð8rB   c                ó  — |                      d|j        v rdnd¦  «         |j                             d¦  «        }|j                             d¦  «        }|j        j        j        }|j        j        }|rJt          t          |¦  «        ¦  «        }| 	                    |g¬¦  «         |  
                    |||¦  «         |rLt          t          |¦  «        ¦  «        }| 	                    |g¬¦  «         |  
                    |||¦  «         dS dS )	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_metricsrt   rr   zlk.user_inputzlk.response.textr’   r”   N)r|   r—   rl   ru   rv   rP   Ú
start_timer   r6   r™   Ú_append_transcriptr   )rN   ro   Ú
user_inputÚresponserP   ÚstartÚmsgs          r@   r�   z*LiveKitLangSmithSpanProcessor._handle_turn9  s  € ð 	�ŠØ0°EÔ4DÐDÐDˆEˆEÈ'ñ	
ô 	
ð 	
ð Ô%×)Ò)¨/Ñ:Ô:ˆ
ØÔ#×'Ò'Ð(:Ñ;Ô;ˆØ”:Ô%Ô.ˆØ”
Ô%ˆØð 	:Ý$¥S¨¡_¤_Ñ5Ô5ˆCØ×Ò s eÐÑ,Ô,Ð,Ø×#Ò# H¨c°5Ñ9Ô9Ð9Øð 	:Ý)­#¨h©-¬-Ñ8Ô8ˆCØ×Ò¨3¨%ÐÑ0Ô0Ð0Ø×#Ò# H¨c°5Ñ9Ô9Ð9Ð9Ð9ð	:ð 	:rB   ÚmessageÚdictÚsort_keyc                ó€   — | j                              |¦  «        pg }|                     ||f¦  «         || j         |<   dS )zIAppend a message to the transcript the root rolls up, keyed for ordering.N)rF   rl   r¥   )rN   rP   rµ   r·   Úconversations        r@   r°   z0LiveKitLangSmithSpanProcessor._append_transcriptP  sI   € àÔ0×4Ò4°XÑ>Ô>ÐDÀ"ˆØ×Ò˜X wÐ/Ñ0Ô0Ð0à.:ˆÔ! (Ñ+Ð+Ð+rB   c                ó  — |                      d¦  «         |j                             d¦  «        }|€dS t          |¦  «        }| j                             |¦  «        }|rj|                     d¦  «        }|r|| j        |<   n| j                             |d¦  «         |                      ||¦  «         |                      |¦  «         dS | j                             |¦  «        pg }| 	                    |¦  «         || j        |<   dS )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.
        rr   zlangsmith.metadata.thread_idNTr   F)
r|   r—   rl   r6   rM   rk   Ú_apply_user_transcriptÚ_exportrL   r¥   )rN   ro   ÚthreadÚpendingr[   Úhelds         r@   rƒ   z3LiveKitLangSmithSpanProcessor._handle_user_speakingY  s  € ð 	�Š�wÑÔÐØÔ!×%Ò%Ð&DÑEÔEˆØˆ>Ø�4Ý�V‘”ˆàÔ0×4Ò4°VÑ<Ô<ˆØð 	Ø Ÿš Q™œˆJØð AØ9@�Ô.¨vÑ6Ð6àÔ.×2Ò2°6¸4Ñ@Ô@Ð@Ø×'Ò'¨¨zÑ:Ô:Ð:Ø�LŠL˜ÑÔÐØ�5àÔ+×/Ò/°Ñ7Ô7Ð=¸2ˆØ�Š�EÑÔÐØ/3ˆÔ$ VÑ,ØˆurB   r[   c                ó¦  — t          |¦  «        }| j                             |¦  «        }|rj|                     d¦  «        }|r|| j        |<   n| j                             |d¦  «         |                      ||¦  «         |                      |¦  «         dS | j                             |¦  «        pg }|                     |¦  «         || j        |<   dS )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)r6   rL   rl   rk   r»   r¼   rM   r¥   )rN   rR   r[   Útidr¿   ro   r¾   s          r@   r^   z5LiveKitLangSmithSpanProcessor._record_user_transcriptv  sÚ   € õ �)‰nŒnˆØÔ+×/Ò/°Ñ4Ô4ˆØð 	Ø—H’H˜Q‘K”KˆEØð <Ø48�Ô,¨SÑ1Ð1àÔ,×0Ò0°°dÑ;Ô;Ð;Ø×'Ò'¨¨zÑ:Ô:Ð:Ø�LŠL˜ÑÔÐØˆFØÔ0×4Ò4°SÑ9Ô9Ð?¸RˆØ�Š�zÑ"Ô"Ð"Ø.5ˆÔ& sÑ+Ð+Ð+rB   c                óø   — |                      d¦  «         |rb||j        d<   t          |¦  «        }|                     |g¬¦  «         |                      |j        j        j        ||j        j        ¦  «         dS dS )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.
        rt   r�   r’   N)	r|   r—   r   r™   r°   ru   rv   rP   r¯   )rN   ro   r[   r´   s       r@   r»   z4LiveKitLangSmithSpanProcessor._apply_user_transcript‹  s’   € ð 	�Š�uÑÔÐØð 	Ø5?ˆEÔÐ1Ñ2Ý$ ZÑ0Ô0ˆCØ×Ò s eÐÑ,Ô,Ð,Ø×#Ò#Ø”
Ô"Ô+¨S°%´*Ô2Gñô ð ð ð ð		ð 	rB   c                óÌ   — |€dS t          |¦  «        }| j                             |d¦  «        pg D ]}|                      |¦  «         Œ| j                             |d¦  «         dS )zJExport held ``user_speaking`` spans untranscribed (no transcript arrived).N)r6   rL   rk   r¼   rM   )rN   rR   rÁ   ro   s       r@   r…   z2LiveKitLangSmithSpanProcessor._flush_user_speaking›  ss   € àÐØˆFÝ�)‰nŒnˆØÔ1×5Ò5°c¸4Ñ@Ô@ÐFÀBð 	 ð 	 ˆEØ�LŠL˜ÑÔÐÐØÔ&×*Ò*¨3°Ñ5Ô5Ð5Ð5Ð5rB   c                óv  — |                      d¦  «         |j                             d¦  «        }|r#|                     dt	          |¦  «        ¦  «         |j                             d¦  «        }|�|                     |¦  «         |j                             d¦  «        }|�|                     |¦  «         dS dS )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)r|   r—   rl   Úset_metadatar6   Úset_tool_inputÚset_tool_output)rN   ro   rÅ   ÚargsÚoutputs        r@   rˆ   z*LiveKitLangSmithSpanProcessor._handle_tool¤  s¿   € à�Š�vÑÔÐØÔ$×(Ò(Ð)@ÑAÔAˆ	Øð 	<Ø×Ò˜{­C°	©N¬NÑ;Ô;Ð;ØÔ×#Ò#Ð$@ÑAÔAˆØÐØ× Ò  Ñ&Ô&Ð&ØÔ!×%Ò%Ð&?Ñ@Ô@ˆØÐØ×!Ò! &Ñ)Ô)Ð)Ð)Ð)ð ÐrB   c                ó:  — |                      d¦  «         |                     d¦  «         |                     dd¦  «         |                     dd¦  «         |                     dt          d¦  «        pd	¦  «         || j        |<   |                      |¦  «         d
S )z?Mark the conversation root and defer it until the session ends.rr   TÚls_modalityÚaudioÚls_integrationÚlivekitÚls_integration_versionzlivekit-agentsr\   N)r|   Úset_root_spanrÆ   r   rG   rm   )rN   ro   rP   s      r@   r‹   z*LiveKitLangSmithSpanProcessor._handle_root³  s«   € à�Š�wÑÔÐØ×Ò˜DÑ!Ô!Ð!Ø×Ò˜=¨'Ñ2Ô2Ð2Ø×ÒÐ+¨YÑ7Ô7Ð7Ø×ÒØ$Õ':Ð;KÑ'LÔ'LÐ'RÐPRñ	
ô 	
ð 	
ð 27ˆÔ$ XÑ.Ø×Ò˜HÑ%Ô%Ð%Ð%Ð%rB   F©ÚforcerÓ   c               ó¸  — | j                              |¦  «        }|€dS | j                             |¦  «        }|s|| j        vrdS |�|| j        v rdS | j                              |d¦  «         |                      |¦  «         |                      |¦  «         |�|                      ||¦  «         |  	                    |¦  «         |  
                    |¦  «         dS )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)rG   rl   r†   rH   rI   rk   Ú_render_conversationÚ_attach_audio_recordingÚ_attach_pending_audior¼   Ú_cleanup_trace)rN   rP   rÓ   ro   r½   s        r@   rm   z,LiveKitLangSmithSpanProcessor._maybe_releaseÀ  sö   € ð Ô,×0Ò0°Ñ:Ô:ˆØˆ=ØˆFØÔ)×-Ò-¨hÑ7Ô7ˆØð 	Ø˜tÔ9Ð9Ð9Ø�ØÐ! f°Ô0PÐ&PÐ&PØ�àÔ$×(Ò(¨°4Ñ8Ô8Ð8Ø×!Ò! %Ñ(Ô(Ð(Ø×$Ò$ UÑ+Ô+Ð+ØÐØ×&Ò& u¨fÑ5Ô5Ð5Ø�Š�UÑÔÐØ×Ò˜HÑ%Ô%Ð%Ð%Ð%rB   c                óÆ   — | j                              |j        j        j        g ¦  «        }|sdS d„ t          |d„ ¬¦  «        D ¦   «         }|                     |¬¦  «         dS )zJSet the whole transcript (ordered by span start_time) as the root's input.Fc                ó   — g | ]\  }}|‘ŒS rž   rž   )r¡   Ú_r´   s      r@   r£   zFLiveKitLangSmithSpanProcessor._render_conversation.<locals>.<listcomp>Þ  s   € ÐJÐJÐJ™F˜A˜s�CÐJÐJÐJrB   c                ó   — | d         S )Nr   rž   )r¢   s    r@   ú<lambda>zDLiveKitLangSmithSpanProcessor._render_conversation.<locals>.<lambda>Þ  s
   € ÀAÀaÄD€ rB   )Úkeyr’   T)rF   rl   ru   rv   rP   Úsortedr™   )rN   ro   ÚentriesÚmessagess       r@   rÕ   z2LiveKitLangSmithSpanProcessor._render_conversationÙ  sm   € àÔ+×/Ò/°´
Ô0BÔ0KÈRÑPÔPˆØð 	Ø�5ØJÐJ¥f¨W¸.¸.Ð&IÑ&IÔ&IÐJÑJÔJˆØ×Ò (ÐÑ+Ô+Ð+ØˆtrB   c                ó¤  — | j                              |¦  «        }| j                             |d ¦  «         |                      |¦  «         | j                             |d ¦  «         |�h| j                             |d ¦  «         | j                             |d ¦  «         | j                             |d ¦  «         |  	                    |¦  «         d S d S ©N)
r†   rl   rF   rk   Ú_forget_thread_idrH   rK   rI   rJ   r…   )rN   rP   r½   s      r@   rØ   z,LiveKitLangSmithSpanProcessor._cleanup_traceâ  sÑ   € àÔ)×-Ò-¨hÑ7Ô7ˆØÔ!×%Ò% h°Ñ5Ô5Ð5Ø×Ò˜xÑ(Ô(Ð(ØÔ"×&Ò& x°Ñ6Ô6Ð6ØÐØÔ!×%Ò% f¨dÑ3Ô3Ð3ØÔ,×0Ò0°¸Ñ>Ô>Ð>ØÔ)×-Ò-¨f°dÑ;Ô;Ð;Ø×%Ò% fÑ-Ô-Ð-Ð-Ð-ð	 ÐrB   c                ó   •— t          | j        ¦  «        D ]}|                      |d¬¦  «         Œt          | j                             ¦   «         ¦  «        D ]}|                      |¦  «         Œt          ¦   «                              ¦   «          dS )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)ÚlistrG   rm   rL   Úkeysr…   rC   Úshutdown)rN   rP   r½   rO   s      €r@   rè   z&LiveKitLangSmithSpanProcessor.shutdownî  s”   ø€ õ ˜TÔ9Ñ:Ô:ð 	6ð 	6ˆHØ×Ò °ÐÑ5Ô5Ð5Ð5Ý˜4Ô7×<Ò<Ñ>Ô>Ñ?Ô?ð 	.ð 	.ˆFØ×%Ò% fÑ-Ô-Ð-Ð-Ý‰Œ×ÒÑÔÐÐÐrB   é0u  Útimeout_millisc                óF   •— t          ¦   «                              |¦  «        S )uE   Force-flush the downstream â€” deferred root spans are NOT finalized.)rC   Úforce_flush)rN   rê   rO   s     €r@   rì   z)LiveKitLangSmithSpanProcessor.force_flushú  s   ø€ å‰wŒw×"Ò" >Ñ2Ô2Ð2rB   c                ó  — | j         €dS |                       ¦   «         }|�|                     ¦   «         sdS 	 |                     ¦   «         }n# t          $ r Y dS w xY w|                      ||j        || j        ¬¦  «         dS )z>Embed audio from the local ``audio_path_provider`` file (dev).Nri   )r/   ÚexistsÚ
read_bytesÚ	ExceptionÚ_attach_audiord   rE   )rN   ro   Ú
audio_pathÚaudio_bytess       r@   rÖ   z5LiveKitLangSmithSpanProcessor._attach_audio_recording   s¯   € àÔ#Ð+ØˆFØ×-Ò-Ñ/Ô/ˆ
ØÐ Z×%6Ò%6Ñ%8Ô%8ÐØˆFð	Ø$×/Ò/Ñ1Ô1ˆKˆKøÝð 	ð 	ð 	ØˆFˆFð	øøøà×ÒØØ”ØØÔ+ð	 	ñ 	
ô 	
ð 	
ð 	
ð 	
s   ·A Á
AÁAr½   c                óÄ   — | j                              |d¦  «        }|r|                     d¦  «        sdS |                      ||d         |d         |d         ¬¦  «         dS )zCEmbed a recording supplied via :meth:`complete_recording` (egress).Nrf   rd   re   ri   )rJ   rk   rl   rñ   )rN   ro   r½   r¾   s       r@   r×   z3LiveKitLangSmithSpanProcessor._attach_pending_audio  sz   € àÔ/×3Ò3°F¸DÑAÔAˆØð 	˜gŸkšk¨&Ñ1Ô1ð 	ØˆFØ×ÒØØ˜”Ø˜”Ø˜kÔ*ð	 	ñ 	
ô 	
ð 	
ð 	
ð 	
rB   c                óÚ  — t          |j                             ¦   «         ¦  «        D ]Ÿ}|                     d¦  «        sŒ|j        |         }d|                     dd¦  «        › �}t          |¦  «        }|�<t          ||¦  «                             ¦   «         D ]\  }}||j        vr
||j        |<   ŒŒ‹||j        v rŒ•||j        |<   Œ t          |j         	                    d¦  «        ¦  «        p&t          |j         	                    d¦  «        ¦  «        }| 
                    |¦  «         d|j        v r4d	|j        vr-t          |j        d         ¦  «        }	|	r |j        d
i |	¤Ž dS dS dS dS )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   rl   r˜   r   r¦   )
rN   ro   rÞ   ÚvalueÚflat_keyÚparsedrd   Úvalr©   rª   s
             r@   Ú_pre_exportz)LiveKitLangSmithSpanProcessor._pre_export  sÃ  € õ ˜Ô(×-Ò-Ñ/Ô/Ñ0Ô0ð 	/ð 	/ˆCØ—>’> %Ñ(Ô(ð ØØÔ$ SÔ)ˆEØD¨S¯[ª[¸¸cÑ-BÔ-BÐDÐDˆHÝ*¨5Ñ1Ô1ˆFØÐ!Ý!EØ˜Hñ"ô "ç’%‘'”'ð5ð 5‘I�D˜#ð  5Ô#3Ð3Ð3Ø14˜Ô(¨Ñ.øØØ˜5Ô+Ð+Ð+ØØ).ˆEÔ˜XÑ&Ð&õ &ØÔ× Ò Ð!7Ñ8Ô8ñ
ô 
ð Gå Ô 0× 4Ò 4°_Ñ EÔ EÑFÔFð 	ð 	×Ò˜8Ñ$Ô$Ð$ð
 (¨5Ô+;Ð;Ð;Ø*°%Ô2BÐBÐBå*ØÔ Ð!<Ô=ñô ˆEð ð )Ø�”Ð(Ð( %Ð(Ð(Ð(Ð(Ð(ð <Ð;ØBÐBð
)ð )rB   rã   )r2   r3   r,   r4   r-   r4   r.   r4   r/   r5   r0   r6   r1   r7   r8   r   r9   r:   )rP   rQ   rR   r6   r9   r:   )rU   r   rR   r6   r9   r:   )rR   r6   r9   r:   )
rR   r6   rf   rg   rd   r6   re   r4   r9   r:   )ro   r   r9   rp   )ro   r   r9   r:   )rP   rQ   rµ   r¶   r·   r   r9   r:   )rR   r6   r[   r6   r9   r:   )ro   r   r[   r6   r9   r:   )rR   r4   r9   r:   )ro   r   rP   rQ   r9   r:   )rP   rQ   rÓ   rp   r9   r:   )rP   rQ   r9   r:   )r9   r:   )ré   )rê   rQ   r9   rp   )ro   r   r½   r6   r9   r:   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚDEFAULT_STATE_TTL_SECONDSrD   rT   ra   rc   rn   rŒ   rx   rz   r~   r�   r°   rƒ   r^   r»   r…   rˆ   r‹   rm   rÕ   rØ   rè   rì   rÖ   r×   rþ   Ú__classcell__)rO   s   @r@   r+   r+   E   s¡  ø€ € € € € ØSÐSð 9=ð3Rð "&Ø!%Ø"&ØFJØ*Ø#<ð3Rð 3Rð 3Rð 3Rð 3Rð 3Rð 3Rð 3Rðj4ð 4ð 4ð 4ð 4ð 4ðð ð ð ðB@ð @ð @ð @ð $Ø#'ð*ð *ð *ð *ð *ð *ð6#ð #ð #ð #ðN*ð *ð *ð *ð 
ð 
ð 
ð 
ðB9ð 9ð 9ð 9ð2:ð :ð :ð :ð.;ð ;ð ;ð ;ðð ð ð ð:6ð 6ð 6ð 6ð*ð ð ð ð 6ð 6ð 6ð 6ð*ð *ð *ð *ð&ð &ð &ð &ð >Cð &ð &ð &ð &ð &ð &ð2ð ð ð ð
.ð 
.ð 
.ð 
.ð
ð 
ð 
ð 
ð 
ð 
ð3ð 3ð 3ð 3ð 3ð 3ð 3ð
ð 
ð 
ð 
ð$

ð 

ð 

ð 

ð')ð ')ð ')ð ')ð ')ð ')ð ')ð ')rB   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  r?   rw   ry   r{   r}   r   r€   r„   r‡   r‰   r‚   r    rŸ   r+   rž   rB   r@   ú<module>r     s  ððð ð #Ð "Ð "Ð "Ð "Ð "à *Ð *Ð *Ð *Ð *Ð *Ø Ð Ð Ð Ð Ð Ø *Ð *Ð *Ð *Ð *Ð *Ð *Ð *Ð *Ð *à Ð Ð Ð Ð Ð Ø 1Ð 1Ð 1Ð 1Ð 1Ð 1à DÐ DÐ DÐ DÐ DÐ Dðð ð ð ð ð ð ð ð ð ð
ð ð ð ð ð ð ð ð
	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð #Ð ØÐ ð €	Ø#Ð Ø Ð"3Ð4Ð Ø#Ð Ø Ð"3Ð4Ð Ø€
Ø€Ø€
Ø+Ð Ø%Ð ð
 &Ø!Ø +Ø!ð	ð Ð ð $Ð ð@)ð @)ð @)ð @)ð @)Ð$>ñ @)ô @)ð @)ð @)ð @)rB   