Ë
    ³Œj‹p  ã            
      óÐ  — d Z ddlmZ ddlZddl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mZmZ ddl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"dZ#dZ$dZ%d#d„Z&d#d„Z'd$d„Z(d e)«       fd%d„Z*d&d„Z+d'd„Z,d(d„Z-d)d„Z.d*d„Z/d+d„Z0d,d„Z1d-d„Z2 G d„ d«      Z3 G d„ d «      Z4de"ddddeddd!œ		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d.d"„Z5y)/u«  LangSmith tracing for the OpenAI Agents SDK realtime backend.

The Agents SDK's realtime sessions emit no local SDK trace spans (realtime
tracing is server-side only), so the existing batch ``OpenAIAgentsTracingProcessor``
captures nothing here. This is a separate, complementary integration:
:func:`wrap_realtime_session` wraps the ``RealtimeSession`` so the trace is built
from its **semantic event stream**, while the caller's ``async for event in
session`` loop is left untouched.

The conversation is reconstructed from the full ``history`` snapshot the session
delivers on every ``history_updated`` â€” not from the streamed events, which
mis-deliver user messages and emit the assistant transcript as growing partials.
Snapshots are folded into an item map keyed by stable ``item_id`` (latest text
per id wins â†’ partials collapse); each finalized message emits one span (a
curated ``user_message`` or an assistant ``model`` ``llm`` span), grouped into
turns. Each SDK-run tool becomes a single ``tool`` span spanning its
``tool_start``â†’``tool_end`` pair (so the span duration is the real tool latency);
``audio_interrupted`` flags the turn. Token usage â€” which the SDK exposes no
*semantic* event for â€” is recovered from the raw ``response.done`` the SDK still
forwards as a ``raw_model_event`` (``raw_server_event``), then attached to that
turn's assistant ``model`` span so the conversation is priced (audio tokens
included).

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

    realtime_session                                   (root; transcript + WAV)
    â”œâ”€â”€ turn                                           (latency_ms, was_interrupted)
    â”‚   â”œâ”€â”€ user_message                               (curated user msg, from history)
    â”‚   â”œâ”€â”€ lookup_weather                             (tool â€” args in / output out)
    â”‚   â””â”€â”€ model             (assistant message)      (llm â€” from history)
    â””â”€â”€ turn â€¦
é    )ÚannotationsN)ÚTYPE_CHECKINGÚAnyÚCallableÚOptional)Úget_package_version)Úobserve_safely)ÚDEFAULT_MAX_AUDIO_SECONDSÚEventSessionÚstart_session)Úusage_metadata_from_usage)Útracing_context)ÚSequence)ÚClientÚRunTree)ÚWriteReplicaiÀ]  é   é2   éÈ   c           	     ót   — | �*t        | t        t        t        t        t
        t        f«      r| S t        | «      S )zIKeep JSON-able values as-is; repr anything exotic so a span never breaks.)Ú
isinstanceÚstrÚintÚfloatÚboolÚdictÚlistÚrepr)Úvalues    úy/var/www/html/Fitness-lenito-AI-main/venv/lib/python3.12/site-packages/langsmith/integrations/openai_realtime/_session.pyÚ
_stringifyr!   L   s,   € à€}œ
 5¬3´´U¼DÄ$ÌÐ*MÔNØˆÜ�‹;Ðó    c                ó–   — t        | dd«      }t        |t        «      r|S t        | «      }t	        |«      t
        k  r|S |dt
         dz   S )z=Last-resort view of a value we won't (or can't) recurse into.ÚnameNõ   â€¦)Úgetattrr   r   r   ÚlenÚ	_MAX_REPR)r   r$   Útexts      r    Ú_shallowr*   S   sJ   € ä�5˜& $Ó'€DÜ�$œÔØˆÜ�‹;€DÜ�t“9¤	Ò)ˆ4ÐG¨t°J´YÐ/?À%Ñ/GÐGr"   c           	     óŒ  — t        j                  | «      rSt        | t        «      sCt        j                  | «      D �ci c]$  }|j
                  t        | |j
                  d«      “Œ& }}nt        | dd«      }|sy|j                  «       D ��ci c]&  \  }}|j                  d«      rŒt        |«      rŒ$||“Œ( c}}S c c}w c c}}w )z?Public, non-callable attributes of a dataclass/object, or None.NÚ__dict__Ú_)
ÚdataclassesÚis_dataclassr   ÚtypeÚfieldsr$   r&   ÚitemsÚ
startswithÚcallable)r   Úfr1   ÚkÚvs        r    Ú_public_fieldsr8   \   sµ   € ô ×Ñ Ô&¬z¸%ÄÔ/Fä:E×:LÑ:LÈUÔ:Só
Ù:S°QˆA�F‰F”G˜E 1§6¡6¨4Ó0Ñ0Ð:Sð 	ñ 
ô ˜ 
¨DÓ1ˆÙØàŸ™œôÙ'‘��A¨q¯|©|¸CÕ/@ÌÐRSÍˆˆ1‰˜òð ùò
ùós   ½)B;ÂC Â&C Â2C c           
     óø  — | � t        | t        t        t        t        f«      r| S t        | t
        t        t        f«      rdt        t        | «      «      › d�S |t        k\  rt        | «      S t        | «      |v ry|t        | «      hz  }t        | t        «      r‹i }t        | j                  «       «      D ]k  \  }\  }}|t        k\  rdt        | «      t        z
  › d�|d<    |S t        |t        «      r|j!                  d«      rŒPt#        ||d	z   |«      |t        |«      <   Œm |S t        | t$        t&        t(        f«      rht%        | «      }|dt         D �cg c]  }t#        ||d	z   |«      ‘Œ }	}t        |«      t        kD  r%|	j+                  d
t        |«      t        z
  › d�«       |	S t-        | «      }
|
r2|
j                  «       D ��ci c]  \  }}|t#        ||d	z   |«      “Œ c}}S t        | «      S c c}w c c}}w )a	  Recursively coerce any value into a compact, JSON-able span payload.

    Keeps readable data and strips what would break or bloat a span: raw bytes,
    callables, private attributes, and anything past the depth/width caps. Cycles
    are broken via ``seen``.
    NÚ<z bytes>z
<circular>Ú+z morer%   r-   é   u   â€¦ +)r   r   r   r   r   ÚbytesÚ	bytearrayÚ
memoryviewr'   Ú
_MAX_DEPTHr*   Úidr   Ú	enumerater2   Ú
_MAX_ITEMSr3   Ú_cleanr   ÚtupleÚsetÚappendr8   )r   ÚdepthÚseenÚoutÚiÚkeyÚvalr2   r7   Úcleanedr1   r6   s               r    rD   rD   l   s×  € ð €}œ
 5¬3´´U¼DÐ*AÔBØˆÜ�%œ%¤¬JÐ7Ô8Ø”3”u˜U“|Ó$Ð% WÐ-Ð-à”
ÒÜ˜‹ÐÜ	ˆ%ƒy�DÑØØ”2�e“9�+Ñ€Dä�%œÔØ ˆÜ& u§{¡{£}Ö5‰MˆA‰z��SØ”JŠØ ¤ U£¬jÑ!8Ð 9¸Ð?��E‘
Øð ˆ
ô ˜#œsÔ#¨¯©°sÔ(;ØÜ" 3¨°©	°4Ó8ˆC”�C“ŠMð 6ð ˆ
ä�%œ$¤¤sÐ+Ô,Ü�U“ˆØ7<¸[¼jÑ7IÓJÑ7I°!”6˜!˜U Q™Y¨Õ-Ð7IˆÐJÜˆu‹:œ
Ò"Ø�N‰N˜U¤3 u£:´
Ñ#:Ð";¸5ÐAÔBØˆä˜EÓ"€FÙØ:@¿,¹,¼.ÔI¹.±$°!°Q�”6˜!˜U Q™Y¨Ó-Ñ-¸.ÒIÐIÜ�E‹?Ðùò Kùó Js   ÅG1ÇG6c                ó>   — t        | dd «      xs | �t        | «      S d S )Nr$   )r&   r   )Útools    r    Ú
_tool_namerQ   –   s$   € Ü�4˜ Ó&ÒT¸Ð9I¬4°«:ÐTÈtÐTr"   c                óä   — | €yt        | dd«      }t        | dd«      xs g }g }|D ]2  }t        |dd«      xs t        |dd«      }|sŒ"|j                  |«       Œ4 |dj                  |«      xs dfS )z9Best-effort ``(role, text)`` for a realtime history item.N©NNÚroleÚcontentÚ
transcriptr)   Ú )r&   rG   Újoin)ÚitemrT   rU   ÚpartsÚpartr)   s         r    Ú
_item_textr\   š   s   € à€|ØÜ�4˜ Ó&€DÜ�d˜I tÓ,Ò2°€GØ€EÛˆÜ�t˜\¨4Ó0ÒO´G¸DÀ&È$Ó4OˆÚØ�L‰L˜Õð ð �#—(‘(˜5“/Ò) TÐ*Ð*r"   c                ó    — t        | dd«      }t        |dd«      dk7  ryt        |dd«      xs dj                  «       }|syt        |dd«      |fS )zýExtract the user transcript from a ``raw_model_event``.

    Reads a ``raw_model_event`` wrapping an input-audio transcription completion
    (the wire-level source ``history`` can omit on a barge-in). Returns
    ``(item_id, transcript)`` or None.
    ÚdataNr0   Ú#input_audio_transcription_completedrV   Ú Úitem_id)r&   Ústrip)Úeventr^   rV   s      r    Úraw_input_transcriptrd   ¨   s]   € ô �5˜& $Ó'€DÜˆt�V˜TÓ"Ð&KÒKØÜ˜$ ¨dÓ3Ò9°r×@Ñ@ÓB€JÙØÜ�4˜ DÓ)¨:Ð5Ð5r"   c                óø   — t        | dd«      }t        |dd«      }t        |t        «      r|j                  d«      dk7  ry|j                  d«      }t        |t        «      syt	        |j                  d«      «      S )uÈ  Token usage from a ``raw_model_event`` wrapping a ``response.done``.

    The Agents SDK emits no semantic usage event, but still forwards the raw
    ``response.done`` (as a ``raw_server_event``), which carries ``response.usage``
    â€” the only place per-turn token counts appear on this backend. Maps it via the
    shared Realtime usage mapper (so audio/cached detail is kept). Returns ``None``
    for any other event or a payload without usage.
    r^   Nr0   zresponse.doneÚresponseÚusage)r&   r   r   Úgetr   )rc   r^   Úrawrf   s       r    Úraw_response_usagerj   ¸   sk   € ô �5˜& $Ó'€DÜ
�$˜ Ó
%€CÜ�cœ4Ô  C§G¡G¨F£O°Ò$FØØ�w‰w�zÓ"€HÜ�h¤Ô%ØÜ$ X§\¡\°'Ó%:Ó;Ð;r"   c                óX   — t        | dd«      }t        |«      \  }}t        |dd«      ||fS )zF``(item_id, role, text)`` for a ``history_added`` event's single item.rY   Nra   )r&   r\   )rc   rY   rT   r)   s       r    Úhistory_itemrl   Ë   s4   € ä�5˜& $Ó'€DÜ˜DÓ!�J€Dˆ$Ü�4˜ DÓ)¨4°Ð5Ð5r"   c                ó�   — g }t        | dd«      xs g D ]/  }t        |«      \  }}|j                  t        |dd«      ||f«       Œ1 |S )zK``(item_id, role, text)`` for every item in a ``history_updated`` snapshot.ÚhistoryNra   )r&   r\   rG   )rc   rJ   rY   rT   r)   s        r    Úhistory_messagesro   Ò   sS   € à;=€CÜ˜˜y¨$Ó/Ò5°2Ò5ˆÜ Ó%‰
ˆˆdØ�
‰
”G˜D )¨TÓ2°D¸$Ð?Õ@ð 6ð €Jr"   c                óü  — t        | dd«      xs t        | «      }t        | «      }t        |t        «      r|nd|i}||d<   d}|dv rt        t        | dd«      dd«      |d<   �n•|dk(  r6t        t        | d	d«      «      |d	<   t        t        | d
d«      «      |d
<   d}�nZ|dk(  rMt        t        | d	d«      «      |d	<   t        t        | d
d«      «      |d
<   t        t        | dd«      «      |d<   �n|dk(  rt        | dd«      |d<   nò|dk(  r*t        t        | dd«      «      \  }}||c|d<   |d<   |dk(  }nÃ|dk(  rEt        | dd«      xs g }|rt        |d   «      nd\  }}||c|d<   |d<   t        |«      |d<   |dk(  }ny|dk(  r7t        t        | dd«      dd«      |d<   t        t        | dd«      dd«      |d<   n=|dk(  rt        t        | d d«      «      |d <   n|d!k(  rt        t        | d!d«      «      |d!<   |||fS )"z9Map a session event to ``(name, span_payload, inbound)``.r0   Nr   F©Úagent_startÚ	agent_endÚagentr$   Ú
tool_startrP   Ú	argumentsTÚtool_endÚoutputÚaudio_interruptedra   Úhistory_addedrY   rT   r)   ÚuserÚhistory_updatedrn   éÿÿÿÿrS   Ú	last_roleÚ	last_textÚlengthÚhandoffÚ
from_agentÚto_agentÚguardrail_trippedÚmessageÚerror)	r&   r   rD   r   r   rQ   r!   r\   r'   )rc   ÚetypeÚdumpedÚpayloadÚinboundrT   r)   rn   s           r    Údescribe_eventr‹   Û   sA  € ä�E˜6 4Ó(Ò7¬D°«K€EÜ�E‹]€FÜ(2°6¼4Ô(@™fÀwÐPVÐFW€GØ€GˆF�OØ€GàÐ,Ñ,Ü"¤7¨5°'¸4Ó#@À&È$ÓOˆ�ÓØ	�,Ò	Ü$¤W¨U°F¸DÓ%AÓBˆ�‰Ü)¬'°%¸ÀdÓ*KÓLˆ�ÑØŠØ	�*Ò	Ü$¤W¨U°F¸DÓ%AÓBˆ�‰Ü)¬'°%¸ÀdÓ*KÓLˆ�ÑÜ&¤w¨u°hÀÓ'EÓFˆ�ÓØ	Ð%Ò	%Ü$ U¨I°tÓ<ˆ�	ÒØ	�/Ò	!Ü¤¨¨v°tÓ <Ó=‰
ˆˆdØ+/°Ð(ˆ�‰˜ ™Ø˜&‘.‰Ø	Ð#Ò	#Ü˜% ¨DÓ1Ò7°RˆÙ07”Z ¨¡Ô,¸\‰
ˆˆdØ59¸4Ð2ˆ�Ñ˜g kÑ2Ü ›Lˆ�ÑØ˜&‘.‰Ø	�)Ò	Ü 'Ü�E˜<¨Ó.°¸ó!
ˆ�Ñô &¤g¨e°ZÀÓ&FÈÐPTÓUˆ�
ÒØ	Ð%Ò	%Ü'¬°°yÀ$Ó(GÓHˆ�	ÒØ	�'Ò	Ü%¤g¨e°W¸dÓ&CÓDˆ�Ñà�'˜7Ð"Ð"r"   c                ó    — t        | dd«      }t        |t        «      r|xs dS dD ]&  }t        ||d«      }t        |t        «      sŒ!|sŒ$|c S  y)a  Best-effort model name for a ``RealtimeSession`` (attribution only).

    The Agents SDK emits no per-response usage, so this never drives cost; it
    just tags the assistant ``llm`` span with ``ls_model_name``. Returns ``None``
    when the model can't be read from the session.
    ÚmodelN)Ú
model_namer�   )r&   r   r   )Úsessionr�   Úattrr$   s       r    Ú_resolve_modelr‘     sT   € ô �G˜W dÓ+€EÜ�%œÔØŠ}˜ÐÛ'ˆÜ�u˜d DÓ)ˆÜ�dœCÕ ¢TØŠKð (ð r"   c                  óv   — e Zd Z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y)Ú_AgentsRealtimeTracera  Reconstructs the conversation from history snapshots and emits its spans.

    Folds each ``history`` snapshot into a map keyed by stable ``item_id``
    (latest non-empty text wins, so partials collapse), emits one span per
    finalized message (a ``user_message`` or an assistant ``model`` ``llm`` span)
    grouped into per-user-turn ``turn`` spans, and spans ``tool_end`` /
    ``audio_interrupted`` from the live stream. Optionally notifies an
    ``on_message`` callback as finalized transcript lines arrive.
    N©Ú
on_messager�   c               ó¢   — || _         || _        || _        i | _        t	        «       | _        t	        «       | _        d | _        d | _        i | _	        y ©N)
Ú_traceÚ_on_messageÚ_modelÚ_itemsrF   Ú_emittedÚ	_notifiedÚ_latency_sinceÚ_pending_usageÚ_open_tools)Úselfr�   r•   r�   s       r    Ú__init__z_AgentsRealtimeTracer.__init__"  sQ   € ð ˆŒØ%ˆÔØˆŒà13ˆŒÜ"%£%ˆŒÜ/2«uˆŒà,0ˆÔð 6:ˆÔð
 PRˆÕr"   c                ó.  — | j                   j                  «       }t        |dd«      }|€y|dk(  r| j                  |«       y|dk(  rOt	        |«      x}�|| _        t        |«      }|r-|\  }}| j                  |d|fg|«       | j                  d¬«       y|dk(  r/| j                  t        |«      g|«       | j                  d¬«       y|d	k(  r.| j                  t        |«      |«       | j                  d¬«       y|d
v ry|dk(  r| j                  |«       y|dk(  r| j                  ||«       yt        |«      \  }}	}
|dk(  r| j                   j                  d¬«       | j                   j                  |	|||
¬«      5  	 ddd«       y# 1 sw Y   yxY w)zBObserve one session event: fold history, emit spans, time latency.r0   NÚaudioÚraw_model_eventr{   T©Ú	hold_lastrz   r|   rq   ru   rw   ry   )Úwas_interrupted)r$   rŠ   )r˜   Únowr&   Úrecord_first_audiorj   rŸ   rd   Ú_observe_itemsÚ_flushrl   ro   Ú_start_toolÚ	_end_toolr‹   Úadd_turn_metadataÚ
event_span)r¡   rc   Úreceived_atr‡   rg   Úrecra   rV   r$   r‰   rŠ   s              r    Úobservez_AgentsRealtimeTracer.observe;  s£  € à—k‘k—o‘oÓ'ˆÜ˜˜v tÓ,ˆØˆ=Øà�GÒØ×#Ñ# KÔ0ØØÐ%Ò%Ü+¨EÓ2Ð2�Ð?Ø&+�Ô#Ü& uÓ-ˆCÙØ&)Ñ#�˜Ø×#Ñ# g¨v°zÐ%BÐ$CÀ[ÔQØ—‘ d�Ô+ØØ�OÒ#Ø×Ñ¤¨eÓ!4Ð 5°{ÔCØ�K‰K $ˆKÔ'ØØÐ%Ò%Ø×ÑÔ 0°Ó 7¸ÔEØ�K‰K $ˆKÔ'ØØÐ0Ñ0Øð �LÒ Ø×Ñ˜UÔ#ØØ�JÒØ�N‰N˜5 +Ô.Øô "0°Ó!6Ñˆˆg�wØÐ'Ò'Ø�K‰K×)Ñ)¸$Ð)Ô?ð �[‰[×#Ñ# G¨[¸tÈWÐ#ÕUØ÷ V×UÑUús   Æ FÆFc                óþ   — t        t        |dd«      «      }t        t        |dd«      «      }| j                  j	                  |xs ddd|i¬«      }| j
                  j                  ||fg «      j                  |«       y)z:Open a held-open ``tool`` span for a ``tool_start`` event.rP   Nrv   )r$   Úrun_typeÚinputs)rQ   r&   r!   r˜   Ú	open_spanr    Ú
setdefaultrG   )r¡   rc   r$   ÚargsÚruns        r    r­   z!_AgentsRealtimeTracer._start_tooll  sz   € äœ' %¨°Ó6Ó7ˆÜœ' %¨°dÓ;Ó<ˆØ�k‰k×#Ñ#Ø’˜ØØ Ð&ð $ó 
ˆð
 	×Ñ×#Ñ# T¨4 L°"Ó5×<Ñ<¸SÕAr"   c           
     óÒ  — t        t        |dd«      «      }t        t        |dd«      «      }t        t        |dd«      «      }| j                  j	                  ||f«      }|rB|j                  d«      }|s| j                  ||f= | j                  j                  |d|i¬«       y| j                  j                  |||dœ||xs dddd|id|i¬	«      5  	 ddd«       y# 1 sw Y   yxY w)
a  Close the matching open tool span for a ``tool_end`` event.

        Matched on ``(tool_name, arguments)`` FIFO. If no open start matches
        (e.g. tracing began mid-call), fall back to a point-in-time tool span so
        the call is still recorded.
        rP   Nrv   rx   r   )Úoutputs)rP   rv   rx   F)r$   rµ   rŠ   r¶   r¼   )	rQ   r&   r!   r    rh   Úpopr˜   Ú
close_spanr°   )r¡   rc   r±   r$   r¹   rx   Úqueuerº   s           r    r®   z_AgentsRealtimeTracer._end_toolw  sñ   € ô œ' %¨°Ó6Ó7ˆÜœ' %¨°dÓ;Ó<ˆÜœG E¨8°TÓ:Ó;ˆØ× Ñ ×$Ñ$ d¨D \Ó2ˆÙØ—)‘)˜A“,ˆCÙØ×$Ñ$ d¨D \Ð2Ø�K‰K×"Ñ" 3°¸6Ð0BÐ"ÔCØØ�[‰[×#Ñ#Ø¨¸Ñ?ØØ’˜ØØØ Ð&Ø˜vÐ&ð $õ 
ð ÷
÷ 
ñ 
ús   ÃCÃC&c                óì   — | j                  d¬«       | j                  j                  «       D ]+  }|D ]$  }d|_        | j                  j                  |«       Œ& Œ- | j                  j                  «        y)a!  Emit any messages still pending and close orphaned tool spans.

        Called at teardown. A ``tool_start`` whose tool raised (or a session torn
        down mid-call) never gets a ``tool_end``; those spans are closed here with
        an error so they don't dangle open forever.
        Fr¦   z.tool did not complete before the session endedN)r¬   r    Úvaluesr†   r˜   r¾   Úclear)r¡   r¿   rº   s      r    Úflush_pendingz#_AgentsRealtimeTracer.flush_pending“  sb   € ð 	�‰˜eˆÔ$Ø×%Ñ%×,Ñ,Ö.ˆEÛ�ØL�”	Ø—‘×&Ñ& sÕ+ñ ð /ð 	×Ñ×ÑÕ r"   c                ó\  — |D ]§  \  }}}|sŒ
|| j                   vr8|dk(  r3| j                  d¬«       | j                  j                  «        || _        | j                   j                  |«      }|€||dœ| j                   |<   n|r||d<   |r||d<   |dv sŒ“|sŒ–| j                  ||«       Œ© y)	a   Fold ``(item_id, role, text)`` tuples into the map.

        A brand-new user item begins a turn: the previous turn's messages are
        flushed first (so they stay grouped under it), then a new turn opens and
        the latency timer is armed.
        r{   Fr¦   N)rT   r)   rT   r)   ©r{   Ú	assistant)r›   r¬   r˜   Ú
start_turnrž   rh   Ú_notify)r¡   Úseqr±   ÚiidrT   r)   Úcurs          r    r«   z$_AgentsRealtimeTracer._observe_items¡  s­   € ó  #‰OˆC��tÙØØ˜$Ÿ+™+Ñ%¨$°&ª.Ø—‘ e�Ô,Ø—‘×&Ñ&Ô(Ø&1�Ô#Ø—+‘+—/‘/ #Ó&ˆCØˆ{Ø,0¸$Ñ#?�—‘˜CÒ áØ"&�C˜‘KÙØ"&�C˜‘KØÐ,Ò,²Ø—‘˜T 4Õ(ñ!  #r"   c                óÌ   — t        | j                  «      }|rt        |«      dz
  n
t        |«      }|dt        d|«       D ]"  }|| j                  vsŒ| j                  |«       Œ$ y)z Emit not-yet-emitted items in order.

        Optionally holds back the last (still-streaming) item until it is
        superseded or the session ends.
        r<   Nr   )r   r›   r'   Úmaxrœ   Ú_record_item)r¡   r§   ÚidsÚcutoffrÊ   s        r    r¬   z_AgentsRealtimeTracer._flushº  sY   € ô �4—;‘;ÓˆÙ!*”�S“˜A’´°C³ˆØÐ'œ˜Q ›Ó(ˆCØ˜$Ÿ-™-Ò'Ø×!Ñ! #Õ&ñ )r"   c                ó–   — | j                   �=| j                  j                  t        || j                   z
  dz  «      ¬«       d| _         yy)zERecord ``latency_to_first_audio_ms`` on the open turn, once per turn.Niè  )Úlatency_to_first_audio_ms)rž   r˜   r¯   Úround)r¡   r±   s     r    rª   z(_AgentsRealtimeTracer.record_first_audioÆ  sO   € à×ÑÐ*Ø�K‰K×)Ñ)Ü*/Ø  4×#6Ñ#6Ñ6¸$Ñ>ó+ð *ô ð
 #'ˆDÕð +r"   c                ó¦   — | j                   �|r|sy||f| j                  v ry| j                  j                  ||f«       | j                  ||«       y)zCSend one finalized transcript line to the on_message callback once.N)r™   r�   Úadd)r¡   rT   r)   s      r    rÈ   z_AgentsRealtimeTracer._notifyÐ  sN   € à×ÑÐ#©4±tØØ�$ˆ<˜4Ÿ>™>Ñ)ØØ�‰×Ñ˜D $˜<Ô(Ø×Ñ˜˜tÕ$r"   c           	     ó|  — | j                   |   d   }| j                   |   d   xs dj                  «       }|dvr| j                  j                  |«       y|sy| j                  j                  |«       | j	                  ||«       | j
                  j                  ||«       |dk(  rJ| j
                  j                  |d|dœ| j
                  j                  «       dd	d|d
œ¬«      5  	 ddd«       y| j
                  j                  d|d
œ| j                  d| j                  dœ¬«       d| _
        y# 1 sw Y   yxY w)z:Emit one message span for a finalized history item (once).rT   r)   r`   rÅ   Nr{   )ra   rT   rU   Úuser_messageT)rT   rU   )r$   rŠ   r¶   rÆ   Úopenai)Úls_providerÚls_model_name)r¼   Úusage_metadataÚmetadata)r›   rb   rœ   rÕ   rÈ   r˜   Úadd_messager°   r©   Ú
record_llmrŸ   rš   )r¡   rÊ   rT   r)   s       r    rÎ   z"_AgentsRealtimeTracer._record_itemÙ  s,  € à�{‰{˜3Ñ Ñ'ˆØ—‘˜CÑ  Ñ(Ò.¨B×5Ñ5Ó7ˆØÐ,Ñ,Ø�M‰M×Ñ˜cÔ"ØÙØØ�‰×Ñ˜#ÔØ�‰�T˜4Ô Ø�‰×Ñ  dÔ+Ø�6Š>Ø—‘×'Ñ'Ø¨¸DÑAØ—‘—‘Ó!Ø#ØØ &°4Ñ8ð (õ ð ÷ð ð �K‰K×"Ñ"Ø!,¸Ñ>Ø#×2Ñ2Ø)1ÀDÇKÁKÑPð #ô ð
 #'ˆDÕ÷ð ús   Ã'D2Ä2D;)r�   r   r•   ú$Optional[Callable[[str, str], None]]r�   úOptional[str]ÚreturnÚNone)rc   r   rá   râ   )rc   r   r±   r   rá   râ   )rá   râ   )rÉ   zlist[tuple]r±   r   rá   râ   )r§   r   rá   râ   )r±   r   rá   râ   )rT   ú
str | Noner)   rã   rá   râ   )rÊ   r   rá   râ   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r¢   r³   r­   r®   rÃ   r«   r¬   rª   rÈ   rÎ   © r"   r    r“   r“     so   „ ñð <@Ø#ñRàðRð 9ð	Rð
 ðRð 
óRó2/ób	Bóó8!ó)ó2
'ó'ó%ô'r"   r“   c                  ó|   — 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d	„Zy
)Ú_TracedRealtimeSessionuŽ  Async-context-manager proxy over a ``RealtimeSession`` that traces events.

    Delegates the underlying session's ``async with`` and every attribute
    (``send_audio``, â€¦), iterates its events, and observes each. On exit it emits
    any pending messages and finalizes the conversation root (transcript + WAV).
    Exposes ``record_user_audio`` / ``record_agent_audio`` for the stereo WAV.
    c       	        ó  — || _         |xs t        t        j                  «       «      | _        || _        || _        || _        || _        || _	        || _
        |	| _        |
| _        d | _        d | _        d | _        d | _        y r—   )Ú_sessionr   ÚuuidÚuuid4Ú
_thread_idÚ_sample_rateÚ_project_nameÚ_tagsÚ	_metadatar™   Ú_max_audio_secondsÚ_clientÚ	_replicasr˜   Ú_tracerÚ_ctxÚ_aiter)r¡   r�   Ú	thread_idÚsample_rateÚproject_nameÚtagsrÜ   r•   Úmax_audio_secondsÚclientÚreplicass              r    r¢   z_TracedRealtimeSession.__init__   s|   € ð   ˆŒØ#Ò8¤s¬4¯:©:«<Ó'8ˆŒØ'ˆÔØ)ˆÔØˆŒ
Ø!ˆŒØ%ˆÔØ"3ˆÔØˆŒØ!ˆŒð /3ˆŒØ8<ˆŒØˆŒ	Øˆ�r"   c                óB   — t        t        j                  | d«      |«      S )Nrì   )r&   ÚobjectÚ__getattribute__)r¡   r$   s     r    Ú__getattr__z"_TracedRealtimeSession.__getattr__!  s   € Ü”v×.Ñ.¨t°ZÓ@À$ÓGÐGr"   c              ƒ  ó„  K  — | j                   j                  «       ƒ d {  –—†  	 t        | j                  | j                  | j
                  | j                  | j                  | j                  | j                  | j                  dt        d«      ¬«
      }|| _        t        d| j                  i| j                  | j
                  | j                  ¬«      }|j                  «        || _        t!        || j"                  t%        | j                   «      ¬«      | _        | S 7 Œü# t(        $ r• | j                  �S	  | j                  j*                  t-        j.                  «       Ž  n&# t0        $ r t2        j5                  dd¬	«       Y nw xY w | j                   j6                  t-        j.                  «       Ž ƒ d {  –—†7   ‚ w xY w­w)
Nzopenai-agents-realtimezopenai-agents)
rú   rû   rü   rý   rÜ   rþ   rÿ   r   ÚintegrationÚintegration_versionrú   )rÜ   rý   rü   r   r”   zCvoice tracing: error unwinding context after a failed session enterT©Úexc_info)rì   Ú
__aenter__r   rï   rð   rñ   rò   ró   rô   rõ   rö   r   r˜   r   Ú	__enter__rø   r“   r™   r‘   r÷   ÚBaseExceptionÚ__exit__Úsysr	  Ú	ExceptionÚloggerÚdebugÚ	__aexit__)r¡   ÚtraceÚctxs      r    r
  z!_TracedRealtimeSession.__aenter__$  sq  è ø€ Ø�m‰m×&Ñ&Ó(×(Ð(ð$	Ü!ØŸ/™/Ø ×-Ñ-Ø!×/Ñ/Ø—Z‘ZØŸ™Ø"&×"9Ñ"9Ø—|‘|ØŸ™Ø4Ü$7¸Ó$HôˆEð  ˆDŒKÜ!Ø% t§¡Ð7Ø—Z‘ZØ!×/Ñ/ØŸ™ô	ˆCð �M‰MŒOØˆDŒIÜ0Ø $×"2Ñ"2¼.ÈÏÉÓ:WôˆDŒLð ˆðS 	)ùô: ò 	Ø�y‰yÐ$ðØ&�D—I‘I×&Ñ&¬¯©«Ò7øÜ ò Ü—L‘Lð(à!%ð !ö ðúð *�$—-‘-×)Ñ)¬3¯<©<«>Ð:×:Ñ:Øð	üsW   ‚G  D¡G ¦C5D ÄG ÄF=Ä5+E!Å F=Å! FÆF=ÆFÆ1F=Æ5F8Æ6F=Æ=G c              ƒ  óH  K  — 	 | j                   �| j                   j                  «        | j                  �F|�*|j                  › d|› �| j                  j                  _        | j                  j                  «        | j                  �| j                  j                  d d d «       	 | j                  j                  |||«      ƒ d {  –—† S # t        $ r t        j                  dd¬«       Y Œqw xY w# | j                  �| j                  j                  d d d «       w w xY w7 ŒY­w)Nz: z)voice tracing: failed to finalize sessionTr  )r÷   rÃ   r˜   rä   rº   r†   Úfinalizer  r  Úwarningrø   r  rì   r  )r¡   Úexc_typeÚexcÚtbs       r    r  z _TracedRealtimeSession.__aexit__P  sô   è ø€ ð	5Ø�|‰|Ð'Ø—‘×*Ñ*Ô,Ø�{‰{Ð&Ø�?Ø/7×/@Ñ/@Ð.AÀÀCÀ5Ð,I�D—K‘K—O‘OÔ)Ø—‘×$Ñ$Ô&ð �y‰yÐ$Ø—	‘	×"Ñ" 4¨¨tÕ4Ø—]‘]×,Ñ,¨X°s¸BÓ?×?Ð?øô ò 	WÜ�N‰NÐFÐQUˆNÖVð	Wûð �y‰yÐ$Ø—	‘	×"Ñ" 4¨¨tÕ4ð %úà?úsB   ‚D"„A8C Á<A
D"ÃD ÃD"Ã C.Ã+C1 Ã-C.Ã.C1 Ã1,DÄD"c                óD   — | j                   j                  «       | _        | S r—   )rì   Ú	__aiter__rù   )r¡   s    r    r  z _TracedRealtimeSession.__aiter__b  s   € Ø—m‘m×-Ñ-Ó/ˆŒØˆr"   c              ƒ  óø   K  — | j                   }|€!| j                  j                  «       }|| _         |j                  «       ƒ d {  –—† }| j                  � t        | j                  j                  |«       |S 7 Œ2­wr—   )rù   rì   r  Ú	__anext__r÷   r	   r³   )r¡   Úaiterrc   s      r    r  z _TracedRealtimeSession.__anext__f  sd   è ø€ Ø—‘ˆØˆ=Ø—M‘M×+Ñ+Ó-ˆEØˆDŒKØ—o‘oÓ'×'ˆØ�<‰<Ð#Ü˜4Ÿ<™<×/Ñ/°Ô7Øˆð (ús   ‚AA:ÁA8Á3A:c                ó†   — | j                   �5| j                   j                  | j                   j                  «       |«       yy)zCRecord a chunk of user (mic) PCM16 for the stereo conversation WAV.N)r˜   Úrecord_userr©   ©r¡   Úpcms     r    Úrecord_user_audioz(_TracedRealtimeSession.record_user_audiop  s0   € à�;‰;Ð"Ø�K‰K×#Ñ# D§K¡K§O¡OÓ$5°sÕ;ð #r"   c                ó†   — | j                   �5| j                   j                  | j                   j                  «       |«       yy)zGRecord a chunk of agent (played) PCM16 for the stereo conversation WAV.N)r˜   Úrecord_agentr©   r"  s     r    Úrecord_agent_audioz)_TracedRealtimeSession.record_agent_audiou  s0   € à�;‰;Ð"Ø�K‰K×$Ñ$ T§[¡[§_¡_Ó%6¸Õ<ð #r"   N)r�   r   rú   rà   rû   r   rü   rà   rý   úOptional[list[str]]rÜ   úOptional[dict[str, Any]]r•   rß   rþ   úOptional[float]rÿ   úOptional[Client]r   ú Optional[Sequence[WriteReplica]]rá   râ   )r$   r   rá   r   )rá   rê   )r  r   r  r   r  r   rá   r   )rá   r   )r#  r=   rá   râ   )rä   rå   ræ   rç   r¢   r  r
  r  r  r  r$  r'  rè   r"   r    rê   rê   ÷  sŸ   „ ñð àð ð !ð	 ð
 ð ð $ð ð "ð ð +ð ð 9ð ð +ð ð !ð ð 3ð ð 
ó óBHó*óX@ó$óó<ô
=r"   rê   ©	rú   rû   rü   rý   rÜ   r•   rþ   rÿ   r   c       	        ó,   — t        | |||||||||	¬«
      S )a½  Trace an OpenAI Agents SDK ``RealtimeSession`` into LangSmith.

    Returns an async-context-manager proxy that also enters the underlying
    session; iterate and call it exactly as you would the original::

        session = await runner.run()
        async with wrap_realtime_session(session, thread_id=tid) as conn:
            async for event in conn:
                ...

    To capture the stereo conversation WAV, feed PCM via the proxy's
    ``record_user_audio`` / ``record_agent_audio``.

    Args:
        session: the ``RealtimeSession`` returned by ``RealtimeRunner.run()``.
        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.
        on_message: optional callback ``(role, text)`` invoked once per finalized
            transcript line (e.g. to print to a console).
        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Ü   r•   rþ   rÿ   r   s
             r    Úwrap_realtime_sessionr/  {  s0   € ôR "ØØØØ!ØØØØ+ØØôð r"   )r   r   rá   r   )r   r   rá   údict[str, Any] | None)r   r   rH   r   rI   zfrozenset[int]rá   r   )rP   r   rá   rã   )rY   r   rá   ztuple[str | None, str | None])rc   r   rá   ztuple[str | None, str] | None)rc   r   rá   r0  )rc   r   rá   z)tuple[str | None, str | None, str | None])rc   r   rá   z/list[tuple[str | None, str | None, str | None]])rc   r   rá   z tuple[str, dict[str, Any], bool])r�   r   rá   rà   )r�   r   rú   rà   rû   r   rü   rà   rý   r(  rÜ   r)  r•   rß   rþ   r*  rÿ   r+  r   r,  rá   rê   )6rç   Ú
__future__r   r.   Úloggingr  rí   Útypingr   r   r   r   Ú$langsmith._internal._package_versionr   Ú!langsmith._internal.voice.helpersr	   Ú!langsmith._internal.voice.sessionr
   r   r   Ú2langsmith.integrations.openai_realtime._connectionr   Úlangsmith.run_helpersr   Úcollections.abcr   Ú	langsmithr   r   Úlangsmith.run_treesr   Ú	getLoggerrä   r  ÚDEFAULT_SAMPLE_RATEr@   rC   r(   r!   r*   r8   Ú	frozensetrD   rQ   r\   rd   rj   rl   ro   r‹   r‘   r“   rê   r/  rè   r"   r    Ú<module>r?     sb  ðñõB #ã Û Û 
Û ß 9Ó 9å DÝ <÷ñ õ
õ 2áÝ(ç)Ý0à	ˆ×	Ñ	˜8Ó	$€ð Ð à€
Ø€
Ø€	óóHóð  %&¹i»kô 'óTUó+ó6ó <ó&6óó(#óV÷"]'ñ ]'÷@A=ñ A=ðN  $Ø*Ø"&Ø $Ø)-Ø7;Ø)BØ#Ø15ñ4Øð4ð ð4ð ð	4ð
  ð4ð ð4ð 'ð4ð 5ð4ð 'ð4ð ð4ð /ð4ð ô4r"   