§
    ~ŠtjæU  ã            
      ó€  — d Z ddlmZ ddlZddlZddlmZ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 erdd
lmZ ddlmZmZ ddlmZ  ej        e¦  «        ZdZ  e!h d£¦  «        Z"d7d„Z#d8d„Z$d9d„Z%d:d„Z&d;d„Z' G d„ d¦  «        Z( G d„ d ¦  «        Z) G d!„ d"¦  «        Z*de ddddeddd#œ	d<d6„Z+dS )=uÜ  LangSmith tracing for the OpenAI Realtime API (raw WebSocket).

OpenAI Realtime has no native telemetry â€” it's a raw WebSocket event stream of
``input_audio_buffer.*`` / ``response.*`` events. :func:`wrap_realtime` wraps the
``AsyncRealtimeConnection`` so the trace is built directly from that stream while
the caller's ``async for event in connection`` loop is left untouched: each
received event is observed, spanned where warranted, and grouped into turns; the
running transcript and a stereo conversation WAV land on the root span.

Tool nesting is preserved without wrapping the caller's loop body: an event's
span is opened when the event is received and kept as the active LangSmith
context until the *next* event arrives â€” so any ``@traceable`` work the caller
does while handling the event (tool execution) nests under it.

Trace shape â€” one conversation = one trace::

    realtime_session                                   (root; transcript + WAV)
    â”œâ”€â”€ session.created / session.updated              (setup)
    â”œâ”€â”€ turn                                           (latency_ms, was_interrupted)
    â”‚   â”œâ”€â”€ conversation.item.input_audio_transcription.completed   (user message)
    â”‚   â””â”€â”€ response.done                              (chain wrapper)
    â”‚       â”œâ”€â”€ model                                  (llm â€” message + tokens)
    â”‚       â””â”€â”€ <your @traceable tools>                (nested under response.done)
    â””â”€â”€ turn â€¦
é    )ÚannotationsN)ÚTYPE_CHECKINGÚAnyÚCallableÚOptional)Úget_package_version)Ú_create_usage_metadata)Úobserve_safely)ÚDEFAULT_MAX_AUDIO_SECONDSÚEventSessionÚstart_session)Útracing_context)ÚSequence)ÚClientÚRunTree)ÚWriteReplicaiÀ]  >
   úresponse.createdúconversation.item.doneúconversation.item.addedúresponse.output_item.doneúresponse.content_part.doneúresponse.output_audio.doneúresponse.output_item.addedúresponse.content_part.addedúinput_audio_buffer.committedú%response.function_call_arguments.doneÚ
event_typeÚstrÚreturnÚboolc                ó4   — |                       d¦  «        pd| v S )u   Direction of an event relative to the model.

    Inbound = something the user sent toward the model (their speech buffer,
    their transcription) â†’ goes in span ``inputs``. Everything else is the
    model/server talking back â†’ span ``outputs``.
    Úinput_audio_bufferÚinput_audio_transcription)Ú
startswith)r   s    úp/var/www/html/CA-Chatbot/venv/lib/python3.11/site-packages/langsmith/integrations/openai_realtime/_connection.pyÚ
is_inboundr&   I   s(   € ð 	×ÒÐ2Ñ3Ô3ð 	5Ø&¨*Ð4ðó    Úresponser   údict[str, Any]c                ó  — g }g }t          | dd¦  «        pg D ]À}t          |dd¦  «        dk    rZ|                     t          |dd¦  «        dt          |¦  «        t          |dd¦  «        t          |dd¦  «        pd	d
œdœ¦  «         Œqt          |dd¦  «        pg D ];}t          |dd¦  «        pt          |dd¦  «        }|r|                     |¦  «         Œ<ŒÁdd                     |¦  «                             ¦   «         dœ}|r||d<   |S )u   Curated assistant message from a ``response.done`` payload.

    The readable, AIMessage-shaped view of what the model returned this
    response: the spoken text plus any tool calls it requested. Tool calls use
    the OpenAI ChatCompletion shape (``type: "function"`` with a nested
    ``function`` holding the name and the raw JSON ``arguments`` string) â€” that's
    the format the LangSmith UI recognizes and renders inline on the model span;
    a flatter ``{name, args, id}`` shape would instead spill into "Additional
    Fields".
    ÚoutputNÚtypeÚfunction_callÚcall_idÚfunctionÚnameÚ	argumentsz{})r0   r1   )Úidr,   Úindexr/   ÚcontentÚ
transcriptÚtextÚ	assistantú ©Úroler4   Ú
tool_calls)ÚgetattrÚappendÚlenÚjoinÚstrip)r(   Útextsr;   ÚitemÚpartr6   Úouts          r%   Úresponse_assistant_outputrE   V   sT  € ð €EØ')€JÝ˜ (¨DÑ1Ô1Ð7°Rð #ð #ˆÝ�4˜ Ñ&Ô&¨/Ò9Ð9Ø×Òå! $¨	°4Ñ8Ô8Ø&Ý  ™_œ_å '¨¨f°dÑ ;Ô ;õ &-¨T°;ÀÑ%EÔ%EÐ%MÈð	!ð !ð	
ð 
ñô ð ð Ý˜D )¨TÑ2Ô2Ð8°bð 	#ð 	#ˆDÝ˜4 ¨tÑ4Ô4ÐS½ÀÀfÈdÑ8SÔ8SˆDØð #Ø—’˜TÑ"Ô"Ð"øð	#ð $/¸3¿8º8ÀE¹?¼?×;PÒ;PÑ;RÔ;RÐSÐS€CØð 'Ø&ˆˆLÑØ€Jr'   Úusagec                óž  — t          | t          ¦  «        rt          | ¦  «        }nlt          | dd¦  «        }	 t          |¦  «        rt           |¦   «         ¦  «        ni }n# t          $ r i }Y nw xY w|sdD ]}t          | |d¦  «        }|�|||<   ŒdD ]8\  }}|                     |¦  «        }t          |t          ¦  «        r	||vr|||<   Œ9|S )uG  Normalize a Realtime ``usage`` object into the dict the shared mapper reads.

    Realtime spells its per-modality breakdowns ``input_token_details`` /
    ``output_token_details`` (singular "token"), whereas
    :func:`_create_usage_metadata` looks for the Chat-Completions
    ``*_tokens_details`` spelling â€” so we alias them here to let it pick up audio
    and cached-token detail (which dominate voice cost). Falls back to the
    top-level token counts if the object can't be dumped, omitting the detail
    blocks rather than risk passing non-dict values to the mapper.
    Ú
model_dumpN©Úinput_tokensÚoutput_tokensÚtotal_tokens))Úinput_token_detailsÚinput_tokens_details)Úoutput_token_detailsÚoutput_tokens_details)Ú
isinstanceÚdictr<   ÚcallableÚ	ExceptionÚget)rF   ÚbaserH   ÚkeyÚvalÚrealtime_keyÚ
mapper_keyÚblocks           r%   Ú_usage_to_dictr\   }   s  € õ �%�ÑÔð $Ý�E‰{Œ{ˆˆå˜U L°$Ñ7Ô7ˆ
ð	Ý)1°*Ñ)=Ô)=ÐE•4˜
˜
™œÑ%Ô%Ð%À2ˆDˆDøÝð 	ð 	ð 	ØˆDˆDˆDð	øøøàð 	$ØHð $ð $�Ý˜e S¨$Ñ/Ô/�Ø�?Ø #�D˜‘Iøð%ð %ð %Ñ ˆ�jð —’˜Ñ&Ô&ˆÝ�e�TÑ"Ô"ð 	% z¸Ð'=Ð'=Ø$ˆD�ÑøØ€Ks   ¸(A! Á!A0Á/A0údict[str, Any] | Nonec                óœ   ‡— | €dS t          | ¦  «        Št          ˆfd„dD ¦   «         ¦  «        sdS t          t          ‰¦  «        ¦  «        S )a€  Map a Realtime ``usage`` (object or dict) onto LangSmith ``usage_metadata``.

    Delegates to the shared OpenAI usage mapper so the Realtime integration and
    the Chat/Agents wrappers agree on the canonical shape (and so audio/cached
    token detail is captured, not dropped). Returns ``None`` when there is no
    usage or it carries no token counts (e.g. a cancelled turn).
    Nc              3  óF   •K  — | ]}‰                      |¦  «        d uV — Œd S ©N)rU   )Ú.0rW   Ú
usage_dicts     €r%   ú	<genexpr>z,usage_metadata_from_usage.<locals>.<genexpr>ª   sH   øè è € ð ð àð 	�Š�sÑÔ 4Ð'ðð ð ð ð ð r'   rI   )r\   ÚanyrR   r	   )rF   rb   s    @r%   Úusage_metadata_from_usagere   Ÿ   sr   ø€ ð €}ØˆtÝ Ñ&Ô&€JÝð ð ð ð àDðñ ô ñ ô ð ð ˆtÝÕ& zÑ2Ô2Ñ3Ô3Ð3r'   c                ó>   — t          t          | dd¦  «        ¦  «        S )zJMap a ``response.done`` payload's token ``usage`` onto ``usage_metadata``.rF   N)re   r<   )r(   s    r%   Úresponse_usage_metadatarg   ²   s   € å$¥W¨X°wÀÑ%EÔ%EÑFÔFÐFr'   c                  óX   — e Zd ZdZ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S )!Ú_RealtimeTraceru&  Turns the Realtime event stream into a LangSmith trace, one event at a time.

    Decides â€” privately â€” whether to open a span, open/close a turn, append to
    the transcript rollup, set the trace title, time first-audio latency, flag a
    barge-in, and record the ``llm`` span. All trace writes go through the
    injected :class:`EventSession`.

    An event's span is held open (as the active LangSmith parent context) from
    the moment the event is received until the next event arrives, so the
    caller's tool calls nest under it.
    N©Úis_agent_speakingÚsessionr   rk   úOptional[Callable[[], bool]]r   ÚNonec               óL   — || _         || _        d | _        d | _        d | _        d S r`   )Ú_sessionÚ_is_agent_speakingÚ_await_audio_sinceÚ_openÚ_model)Úselfrl   rk   s      r%   Ú__init__z_RealtimeTracer.__init__Ä   s3   € ð  ˆŒð #4ˆÔð 15ˆÔð .2ˆŒ
Ø"&ˆŒˆˆr'   Úeventr   c                ó~  — |                       ¦   «          | j                             ¦   «         }t          |dd¦  «        }|€dS |dv r6t          t          |dd¦  «        dd¦  «        }|rt	          |¦  «        | _        |dk    r|                      |¦  «         dS |                     d¦  «        s	|t          v rdS |dk    r.| j         	                    d	t          |d
d¦  «        pd¦  «         dS |  
                    ||¦  «          | j        j        ||fd|i|                      |¦  «        ¤Ž}|                     ¦   «         }|dk    rdt          |dd¦  «        › �|_        n/|dk    r)t          |dd¦  «        }|�|                      ||¦  «         t!          |¬¦  «        }|                     ¦   «          ||f| _        dS )a"  Observe one received event; span it where warranted.

        Closes the previous event's span first (the caller has finished handling
        it), then applies turn/transcript/latency side-state and, for meaningful
        events, opens a new span kept active until the next call.
        r,   N)zsession.createdzsession.updatedrl   Úmodelzresponse.output_audio.deltaz.deltaz%response.output_audio_transcript.doner7   r5   Ú r0   ú2conversation.item.input_audio_transcription.failedztranscription_failed: Úerrorúresponse.doner(   )Úparent)Ú_close_openrp   Únowr<   r   rt   Ú_record_first_audioÚendswithÚNOISE_EVENTSÚadd_messageÚ_before_spanÚ
event_spanÚ_span_kwargsÚ	__enter__r|   Ú_record_response_llmr   rs   )	ru   rw   Úreceived_atÚetypery   Úcm_spanÚrunr(   Úcm_ctxs	            r%   Úobservez_RealtimeTracer.observe×   s  € ð 	×ÒÑÔÐØ”m×'Ò'Ñ)Ô)ˆÝ˜˜v tÑ,Ô,ˆØˆ=ØˆFð Ð:Ð:Ð:Ý�G E¨9°dÑ;Ô;¸WÀdÑKÔKˆEØð )Ý! %™jœj�”ð Ð1Ò1Ð1Ø×$Ò$ [Ñ1Ô1Ð1ØˆFØ�>Š>˜(Ñ#Ô#ð 	 uµÐ'<Ð'<ØˆFØÐ;Ò;Ð;àŒM×%Ò%Ø�W U¨L¸"Ñ=Ô=ÐCÀñô ð ð ˆFà×Ò˜% Ñ-Ô-Ð-à*�$”-Ô*Ø�;ð
ð 
Ø%*ð
Ø.2×.?Ò.?ÀÑ.FÔ.Fð
ð 
ˆð ×ÒÑ!Ô!ˆØÐHÒHÐHØPµ¸ÀÈÑ1NÔ1NÐPÐPˆCŒIˆIØ�oÒ%Ð%Ý˜u j°$Ñ7Ô7ˆHØÐ#Ø×)Ò)¨#¨xÑ8Ô8Ð8Ý ¨Ð,Ñ,Ô,ˆØ×ÒÑÔÐØ˜vÐ&ˆŒ
ˆ
ˆ
r'   c                ó.   — |                       ¦   «          dS )z5Close any still-open event span (called at teardown).N)r   ©ru   s    r%   Úfinalize_openz_RealtimeTracer.finalize_open  s   € à×ÒÑÔÐÐÐr'   c                ó–   — | j         €d S | j         \  }}d | _         |                     d d d ¦  «         |                     d d d ¦  «         d S r`   )rs   Ú__exit__)ru   rŒ   rŽ   s      r%   r   z_RealtimeTracer._close_open  sU   € ØŒ:ÐØˆFØœ*‰ˆ�ØˆŒ
Ø�Š˜˜d DÑ)Ô)Ð)Ø×Ò˜˜t TÑ*Ô*Ð*Ð*Ð*r'   rŠ   Úfloatc                óæ  — |j         }|dk    rX| j        �/|                      ¦   «         r| j                             d¬¦  «         | j                             ¦   «          d| _        dS |dk    r	|| _        dS |dk    rgt          |dd¦  «        pd                     ¦   «         }|r7| j                             d	|¦  «         | j         	                    |¦  «         dS d| _        dS |d
k    r	d| _        dS dS )zDTurn/transcript/title side-state applied as a span is about to open.z!input_audio_buffer.speech_startedNT)Úwas_interruptedz!input_audio_buffer.speech_stoppedú5conversation.item.input_audio_transcription.completedr5   rz   Úuserr{   )
r,   rq   rp   Úadd_turn_metadataÚ
start_turnrr   r<   r@   r„   Ú	set_title)ru   rw   rŠ   r‹   r6   s        r%   r…   z_RealtimeTracer._before_span  s!  € à”
ˆØÐ7Ò7Ð7ð Ô&Ð2°t×7NÒ7NÑ7PÔ7PÐ2Ø”×/Ò/ÀÐ/ÑEÔEÐEØŒM×$Ò$Ñ&Ô&Ð&Ø&*ˆDÔ#Ð#Ð#ØÐ9Ò9Ð9Ø&1ˆDÔ#Ð#Ð#ØÐMÒMÐMÝ˜E <°Ñ4Ô4Ð:¸×AÒAÑCÔCˆDØð /Ø”×)Ò)¨&°$Ñ7Ô7Ð7Ø”×'Ò'¨Ñ-Ô-Ð-Ð-Ð-à*.�Ô'Ð'Ð'ØÐJÒJÐJØ&*ˆDÔ#Ð#Ð#ð KÐJr'   r)   c                ó¸   — |j         }dt          |¦  «        i}|dk    r0t          |dd¦  «        pd                     ¦   «         }|rd|dœ|d<   n|dk    ri |d	<   |S )
z9Curated, conversation-shaped I/O for the readable events.Úinboundr˜   r5   rz   r™   r9   Úinputsr}   Úoutputs)r,   r&   r<   r@   )ru   rw   r‹   Úkwargsr6   s        r%   r‡   z_RealtimeTracer._span_kwargs+  s�   € à”
ˆØ"+­Z¸Ñ->Ô->Ð!?ˆØÐKÒKÐKÝ˜E <°Ñ4Ô4Ð:¸×AÒAÑCÔCˆDØð EØ,2¸tÐ#DÐ#D��xÑ øØ�oÒ%Ð%ð !#ˆF�9ÑØˆr'   c                óŒ   — | j         �<| j                             t          || j         z
  dz  ¦  «        ¬¦  «         d | _         d S d S )Niè  )Úlatency_to_first_audio_ms)rr   rp   rš   Úround)ru   rŠ   s     r%   r�   z#_RealtimeTracer._record_first_audio9  s_   € ØÔ"Ð.ØŒM×+Ò+Ý*/Ø  4Ô#:Ñ:¸dÑBñ+ô +ð ,ñ ô ð ð
 '+ˆDÔ#Ð#Ð#ð /Ð.r'   r�   r   r(   c                óª   — t          |dd ¦  «        d| j        dœ}| j                             |t	          |¦  «        t          |¦  «        |¬¦  «         d S )NÚstatusÚopenai)r¦   Úls_providerÚls_model_name)r    Úusage_metadataÚmetadata)r<   rt   rp   Ú
record_llmrE   rg   )ru   r�   r(   r«   s       r%   r‰   z$_RealtimeTracer._record_response_llmB  sl   € å˜h¨°$Ñ7Ô7Ø#Ø!œ[ð$
ð $
ˆð
 	Œ× Ò ØÝ-¨hÑ7Ô7Ý2°8Ñ<Ô<Øð	 	!ñ 	
ô 	
ð 	
ð 	
ð 	
r'   )rl   r   rk   rm   r   rn   )rw   r   r   rn   )r   rn   )rw   r   rŠ   r•   r   rn   )rw   r   r   r)   )rŠ   r•   r   rn   )r�   r   r(   r   r   rn   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__rv   r�   r’   r   r…   r‡   r�   r‰   © r'   r%   ri   ri   ·   sÎ   € € € € € ð
ð 
ð  ;?ð	'ð 'ð 'ð 'ð 'ð 'ð&/'ð /'ð /'ð /'ðbð ð ð ð+ð +ð +ð +ð+ð +ð +ð +ð.ð ð ð ð+ð +ð +ð +ð
ð 
ð 
ð 
ð 
ð 
r'   ri   c                  óJ   — e Zd ZdZdd
„Zdd„Zdd„Zdd„Zdd„Zdd„Z	dd„Z
dS )Ú_TracedRealtimeConnectionaî  Transparent proxy over an ``AsyncRealtimeConnection`` that traces events.

    Delegates every attribute to the wrapped connection, so the caller uses it
    exactly like the original (``connection.session.update(...)``,
    ``connection.response.create()``, ``async for event in connection``). Each
    received event is passed to the tracer. Also exposes
    :meth:`record_user_audio` / :meth:`record_agent_audio` so the app can
    (optionally) feed PCM for the stereo conversation WAV.
    Ú
connectionr   Útracerri   rl   r   r   rn   c                ó>   — || _         || _        || _        d | _        d S r`   )Ú_connectionÚ_tracerrp   Ú_aiter)ru   r´   rµ   rl   s       r%   rv   z"_TracedRealtimeConnection.__init__[  s%   € ð
 &ˆÔØˆŒØˆŒØˆŒˆˆr'   r0   r   c                óT   — t          t                               | d¦  «        |¦  «        S )Nr·   )r<   ÚobjectÚ__getattribute__)ru   r0   s     r%   Ú__getattr__z%_TracedRealtimeConnection.__getattr__e  s"   € Ý•v×.Ò.¨t°]ÑCÔCÀTÑJÔJÐJr'   c                óB   — | j                              ¦   «         | _        | S r`   )r·   Ú	__aiter__r¹   r‘   s    r%   r¿   z#_TracedRealtimeConnection.__aiter__h  s   € ØÔ&×0Ò0Ñ2Ô2ˆŒØˆr'   c              ƒ  óÄ   K  — | j         }|€ | j                             ¦   «         }|| _         |                     ¦   «         ƒ d {V —†}t	          | j        j        |¦  «         |S r`   )r¹   r·   r¿   Ú	__anext__r
   r¸   r�   )ru   Úaiterrw   s      r%   rÁ   z#_TracedRealtimeConnection.__anext__l  sh   è è € Ø”ˆØˆ=ØÔ$×.Ò.Ñ0Ô0ˆEØˆDŒKØ—o’oÑ'Ô'Ð'Ð'Ð'Ð'Ð'Ð'ˆÝ�t”|Ô+¨UÑ3Ô3Ð3Øˆr'   c              ƒ  ó|   K  — | j                              ¦   «         ƒ d {V —†}t          | j        j        |¦  «         |S r`   )r·   Úrecvr
   r¸   r�   )ru   rw   s     r%   rÄ   z_TracedRealtimeConnection.recvu  sF   è è € ØÔ&×+Ò+Ñ-Ô-Ð-Ð-Ð-Ð-Ð-Ð-ˆÝ�t”|Ô+¨UÑ3Ô3Ð3Øˆr'   ÚpcmÚbytesc                ój   — | j                              | j                              ¦   «         |¦  «         dS )zCRecord a chunk of user (mic) PCM16 for the stereo conversation WAV.N)rp   Úrecord_userr€   ©ru   rÅ   s     r%   Úrecord_user_audioz+_TracedRealtimeConnection.record_user_audioz  s.   € àŒ×!Ò! $¤-×"3Ò"3Ñ"5Ô"5°sÑ;Ô;Ð;Ð;Ð;r'   c                ój   — | j                              | j                              ¦   «         |¦  «         dS )zGRecord a chunk of agent (played) PCM16 for the stereo conversation WAV.N)rp   Úrecord_agentr€   rÉ   s     r%   Úrecord_agent_audioz,_TracedRealtimeConnection.record_agent_audio~  s.   € àŒ×"Ò" 4¤=×#4Ò#4Ñ#6Ô#6¸Ñ<Ô<Ð<Ð<Ð<r'   N)r´   r   rµ   ri   rl   r   r   rn   )r0   r   r   r   ©r   r³   )r   r   )rÅ   rÆ   r   rn   )r­   r®   r¯   r°   rv   r½   r¿   rÁ   rÄ   rÊ   rÍ   r±   r'   r%   r³   r³   P  s®   € € € € € ðð ðð ð ð ðKð Kð Kð Kðð ð ð ðð ð ð ðð ð ð ð
<ð <ð <ð <ð=ð =ð =ð =ð =ð =r'   r³   c                  ó*   — e Zd ZdZd d„Zd!d„Zd"d„ZdS )#Ú_RealtimeTracingSessionac  Async context manager returned by :func:`wrap_realtime`.

    On enter: starts the conversation root span and session-level LangSmith
    context, returning a traced connection proxy. On exit: closes any open span,
    records an error on the root if the body raised, and finalizes the root
    (rolling up the transcript + attaching the stereo WAV).
    r´   r   Ú	thread_idúOptional[str]Úsample_rateÚintÚproject_nameÚtagsúOptional[list[str]]r«   úOptional[dict[str, Any]]rk   rm   Úmax_audio_secondsúOptional[float]ÚclientúOptional[Client]Úreplicasú Optional[Sequence[WriteReplica]]r   rn   c       	        óü   — || _         |pt          t          j        ¦   «         ¦  «        | _        || _        || _        || _        || _        || _	        || _
        |	| _        |
| _        d | _        d | _        d | _        d S r`   )r·   r   ÚuuidÚuuid4Ú
_thread_idÚ_sample_rateÚ_project_nameÚ_tagsÚ	_metadatarq   Ú_max_audio_secondsÚ_clientÚ	_replicasrp   r¸   Ú_ctx)ru   r´   rÑ   rÓ   rÕ   rÖ   r«   rk   rÙ   rÛ   rÝ   s              r%   rv   z _RealtimeTracingSession.__init__Œ  s{   € ð &ˆÔØ#Ð8¥s­4¬:©<¬<Ñ'8Ô'8ˆŒØ'ˆÔØ)ˆÔØˆŒ
Ø!ˆŒØ"3ˆÔØ"3ˆÔØˆŒØ!ˆŒØ-1ˆŒØ/3ˆŒØˆŒ	ˆ	ˆ	r'   r³   c              ƒ  óº  K  — t          | j        | j        | j        | j        | j        | j        | j        | j        dt          d¦  «        ¬¦
  «
        | _
        t          d| j        i| j        | j        | j        ¬¦  «        | _        | j                             ¦   «          t          | j
        | j        ¬¦  «        | _        t#          | j        | j        | j
        ¦  «        S )Nzopenai-realtimer§   )
rÑ   rÓ   rÕ   rÖ   r«   rÙ   rÛ   rÝ   ÚintegrationÚintegration_versionrÑ   )r«   rÖ   rÕ   rÝ   rj   )r   râ   rã   rä   rå   ræ   rç   rè   ré   r   rp   r   rê   rˆ   ri   rq   r¸   r³   r·   r‘   s    r%   Ú
__aenter__z"_RealtimeTracingSession.__aenter__¨  sØ   è è € Ý%Ø”oØÔ)ØÔ+Ø”Ø”^Ø"Ô5Ø”<Ø”^Ø)Ý 3°HÑ =Ô =ð
ñ 
ô 
ˆŒõ $Ø! 4¤?Ð3Ø”ØÔ+Ø”^ð	
ñ 
ô 
ˆŒ	ð 	Œ	×ÒÑÔÐÝ&ØŒM¨TÔ-Dð
ñ 
ô 
ˆŒõ )¨Ô)9¸4¼<ÈÌÑWÔWÐWr'   Úexc_typeÚexcÚtbr    c              ƒ  óº  K  — 	 | j         �| j                              ¦   «          | j        �6|�|j        › d|› �| j        j        _        | j                             ¦   «          n,# t          $ r t           	                    dd¬¦  «         Y nw xY w| j
        �| j
                             d d d ¦  «         n)# | j
        �| j
                             d d d ¦  «         w w xY wdS )Nz: z)voice tracing: failed to finalize sessionT)Úexc_infoF)r¸   r’   rp   r­   r�   r|   ÚfinalizerT   ÚloggerÚwarningrê   r”   )ru   rï   rð   rñ   s       r%   Ú	__aexit__z!_RealtimeTracingSession.__aexit__Á  sþ   è è € ð	5ØŒ|Ð'Ø”×*Ò*Ñ,Ô,Ð,ØŒ}Ð(Ø�?Ø19Ô1BÐ.KÐ.KÀcÐ.KÐ.K�D”MÔ%Ô+Ø”×&Ò&Ñ(Ô(Ð(øøÝð 	Wð 	Wð 	WÝ�NŠNÐFÐQUˆNÑVÔVÐVÐVÐVð	Wøøøð ŒyÐ$Ø”	×"Ò" 4¨¨tÑ4Ô4Ð4øøð ŒyÐ$Ø”	×"Ò" 4¨¨tÑ4Ô4Ð4Ð4ð %øøøàˆus*   „AA" Á!B2 Á"&BÂB2 Â
BÂB2 Â2&CN)r´   r   rÑ   rÒ   rÓ   rÔ   rÕ   rÒ   rÖ   r×   r«   rØ   rk   rm   rÙ   rÚ   rÛ   rÜ   rÝ   rÞ   r   rn   rÎ   )rï   r   rð   r   rñ   r   r   r    )r­   r®   r¯   r°   rv   rî   r÷   r±   r'   r%   rÐ   rÐ   ƒ  s^   € € € € € ðð ðð ð ð ð8Xð Xð Xð Xð2ð ð ð ð ð r'   rÐ   ©	rÑ   rÓ   rÕ   rÖ   r«   rk   rÙ   rÛ   rÝ   r´   rÑ   rÒ   rÓ   rÔ   rÕ   rÖ   r×   r«   rØ   rk   rm   rÙ   rÚ   rÛ   rÜ   rÝ   rÞ   c       	        ó4   — t          | |||||||||	¬¦
  «
        S )a5  Trace an OpenAI Realtime connection into LangSmith.

    Returns an async context manager that yields a transparent proxy of
    ``connection``; iterate and call it exactly as you would the original::

        async with client.realtime.connect(model=...) as raw, \\
                   wrap_realtime(raw, thread_id=tid) as connection:
            async for event in connection:
                ...

    To capture the stereo conversation WAV, feed PCM via the proxy's
    ``record_user_audio`` / ``record_agent_audio`` and (optionally) supply
    ``is_agent_speaking`` so barge-ins are flagged.

    Args:
        connection: the ``AsyncRealtimeConnection`` from ``client.realtime.connect``.
        thread_id: LangSmith thread id; a random UUID if omitted.
        sample_rate: PCM sample rate of the audio (for the WAV).
        project_name: LangSmith project; defaults to standard ``LANGSMITH_*`` config.
        tags / metadata: attached to the conversation root span.
        is_agent_speaking: zero-arg callable returning whether the agent is still
            audible, used to flag a barge-in; ``None`` disables that flag.
        max_audio_seconds: per-channel cap on audio retained for the WAV, to
            bound memory on long sessions; pass ``None`` to keep all audio.
        client: LangSmith ``Client`` for tracing writes; ``None`` (default) uses
            the SDK's standard env-based resolution (``LANGSMITH_*``).
        replicas: tracing replicas to mirror the conversation trace to additional
            destinations; ``None`` (default) disables replication.
    rø   )rÐ   )
r´   rÑ   rÓ   rÕ   rÖ   r«   rk   rÙ   rÛ   rÝ   s
             r%   Úwrap_realtimerú   Ô  s:   € õT #ØØØØ!ØØØ+Ø+ØØðñ ô ð r'   )r   r   r   r    )r(   r   r   r)   )rF   r   r   r)   )rF   r   r   r]   )r(   r   r   r]   )r´   r   rÑ   rÒ   rÓ   rÔ   rÕ   rÒ   rÖ   r×   r«   rØ   rk   rm   rÙ   rÚ   rÛ   rÜ   rÝ   rÞ   r   rÐ   ),r°   Ú
__future__r   Úloggingrà   Útypingr   r   r   r   Ú$langsmith._internal._package_versionr   Úlangsmith._internal._usager	   Ú!langsmith._internal.voice.helpersr
   Ú!langsmith._internal.voice.sessionr   r   r   Úlangsmith.run_helpersr   Úcollections.abcr   Ú	langsmithr   r   Úlangsmith.run_treesr   Ú	getLoggerr­   rõ   ÚDEFAULT_SAMPLE_RATEÚ	frozensetrƒ   r&   rE   r\   re   rg   ri   r³   rÐ   rú   r±   r'   r%   ú<module>r	     s�  ððð ð4 #Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9à DÐ DÐ DÐ DÐ DÐ DØ =Ð =Ð =Ð =Ð =Ð =Ø <Ð <Ð <Ð <Ð <Ð <ðð ð ð ð ð ð ð ð ð ð
 2Ð 1Ð 1Ð 1Ð 1Ð 1àð 1Ø(Ð(Ð(Ð(Ð(Ð(à)Ð)Ð)Ð)Ð)Ð)Ð)Ð)Ø0Ð0Ð0Ð0Ð0Ð0à	ˆÔ	˜8Ñ	$Ô	$€ð Ð ð ˆyðð ð ñô €ð"
ð 
ð 
ð 
ð$ð $ð $ð $ðNð ð ð ðD4ð 4ð 4ð 4ð&Gð Gð Gð Gð
V
ð V
ð V
ð V
ð V
ñ V
ô V
ð V
ðr0=ð 0=ð 0=ð 0=ð 0=ñ 0=ô 0=ð 0=ðfNð Nð Nð Nð Nñ Nô Nð Nðh  $Ø*Ø"&Ø $Ø)-Ø6:Ø)BØ#Ø15ð5ð 5ð 5ð 5ð 5ð 5ð 5ð 5r'   