§
    ~Štj‹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%dEd„Z&dEd„Z'dFd„Z(d e)¦   «         fdGd„Z*dHd„Z+dId"„Z,dJd%„Z-dKd&„Z.dLd(„Z/dMd*„Z0dNd,„Z1dOd/„Z2 G d0„ d1¦  «        Z3 G d2„ d3¦  «        Z4de"ddddeddd4œ	dPdD„Z5dS )Qu«  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   éÈ   Úvaluer   Úreturnc           	     ó�   — | �4t          | 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)r   s    úm/var/www/html/CA-Chatbot/venv/lib/python3.11/site-packages/langsmith/integrations/openai_realtime/_session.pyÚ
_stringifyr"   L   s3   € à€}�
 5­3µµU½DÅ$ÍÐ*MÑNÔN€}ØˆÝ�‰;Œ;Ðó    c                óÈ   — t          | dd¦  «        }t          |t          ¦  «        r|S t          | ¦  «        }t	          |¦  «        t
          k    r|n|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   s]   € å�5˜& $Ñ'Ô'€DÝ�$�ÑÔð ØˆÝ�‰;Œ;€DÝ�t‘9”9¥	Ò)Ð)ˆ4ˆ4¨t°JµY°JÔ/?À%Ñ/GÐGr#   údict[str, Any] | Nonec                óþ   ‡ — t          j        ‰ ¦  «        r6t          ‰ t          ¦  «        s!ˆ fd„t          j        ‰ ¦  «        D ¦   «         }nt          ‰ dd¦  «        }|sdS d„ |                     ¦   «         D ¦   «         S )z?Public, non-callable attributes of a dataclass/object, or None.c                óH   •— i | ]}|j         t          ‰|j         d ¦  «        “ŒS ©N)r%   r'   )Ú.0Úfr   s     €r!   ú
<dictcomp>z"_public_fields.<locals>.<dictcomp>`   s8   ø€ ð 
ð 
ð 
Ø56ˆAŒF•G˜E 1¤6¨4Ñ0Ô0ð
ð 
ð 
r#   Ú__dict__Nc                ób   — i | ],\  }}|                      d ¦  «        °t          |¦  «        °)||“Œ-S )Ú_)Ú
startswithÚcallable)r0   ÚkÚvs      r!   r2   z"_public_fields.<locals>.<dictcomp>g   sN   € ð ð ð Ù��A¨q¯|ª|¸CÑ/@Ô/@ðÝIQÐRSÉÌðØ	ˆ1ðð ð r#   )ÚdataclassesÚis_dataclassr   ÚtypeÚfieldsr'   Úitems)r   r=   s   ` r!   Ú_public_fieldsr?   \   s§   ø€ õ Ô Ñ&Ô&ð 2­z¸%ÅÑ/FÔ/Fð 2ð
ð 
ð 
ð 
Ý:EÔ:LÈUÑ:SÔ:Sð
ñ 
ô 
ˆˆõ ˜ 
¨DÑ1Ô1ˆØð Øˆtðð ØŸš™œðñ ô ð r#   Údepthr   Úseenúfrozenset[int]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dS ‰t          | ¦  «        hz  Št          | t          ¦  «        r¨i }t          |                      ¦   «         ¦  «        D ]‚\  }\  }}|t          k    r dt          | ¦  «        t          z
  › d�|d<    nPt          |t          ¦  «        r|                     d¦  «        rŒ^t#          |‰d	z   ‰¦  «        |t          |¦  «        <   Œƒ|S t          | t$          t&          t(          f¦  «        rst%          | ¦  «        }ˆˆfd
„|dt          …         D ¦   «         }t          |¦  «        t          k    r.|                     dt          |¦  «        t          z
  › d�¦  «         |S t-          | ¦  «        }	|	r!ˆˆfd„|	                     ¦   «         D ¦   «         S t          | ¦  «        S )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&   r5   é   c                ó8   •— g | ]}t          |‰d z   ‰¦  «        ‘ŒS ©rF   ©Ú_clean)r0   r9   r@   rA   s     €€r!   ú
<listcomp>z_clean.<locals>.<listcomp>‹   s)   ø€ ÐJÐJÐJ°!•6˜!˜U Q™Y¨Ñ-Ô-ÐJÐJÐJr#   u   â€¦ +c                ó@   •— i | ]\  }}|t          |‰d z   ‰¦  «        “ŒS rH   rI   )r0   r8   r9   r@   rA   s      €€r!   r2   z_clean.<locals>.<dictcomp>’   s/   ø€ ÐIÐIÐI±$°!°Q�•6˜!˜U Q™Y¨Ñ-Ô-ÐIÐIÐIr#   )r   r   r   r   r   ÚbytesÚ	bytearrayÚ
memoryviewr(   Ú
_MAX_DEPTHr+   Úidr   Ú	enumerater>   Ú
_MAX_ITEMSr6   rJ   r   ÚtupleÚsetÚappendr?   )
r   r@   rA   ÚoutÚiÚkeyÚvalr>   Úcleanedr=   s
    ``       r!   rJ   rJ   l   s&  øø€ ð €}�
 5­3µµU½DÐ*AÑBÔB€}ØˆÝ�%�%¥­JÐ7Ñ8Ô8ð .Ø-•3•u˜U‘|”|Ñ$Ô$Ð-Ð-Ð-Ð-à•
ÒÐÝ˜‰ŒÐÝ	ˆ%�y„y�DÐÐØˆ|Ø•2�e‘9”9�+Ñ€Då�%�ÑÔð 	Ø ˆÝ& u§{¢{¡}¤}Ñ5Ô5ð 	9ð 	9‰MˆA‰z��SØ•JŠˆØ?¥ U¡¤­jÑ!8Ð?Ð?Ð?��E‘
Ø�Ý˜#�sÑ#Ô#ð ¨¯ª°sÑ(;Ô(;ð ØÝ" 3¨°©	°4Ñ8Ô8ˆC•�C‘”‰MˆMØˆ
å�%�$¥¥sÐ+Ñ,Ô,ð Ý�U‘”ˆØJÐJÐJÐJÐJ°u¸[½j¸[Ô7IÐJÑJÔJˆÝˆu‰:Œ:�
Ò"Ð"Ø�NŠNÐA¥3 u¡:¤:µ
Ñ#:ÐAÐAÐAÑBÔBÐBØˆå˜EÑ"Ô"€FØð JØIÐIÐIÐIÐI¸&¿,º,¹.¼.ÐIÑIÔIÐIÝ�E‰?Œ?Ðr#   Útoolú
str | Nonec                óJ   — t          | dd ¦  «        p| �t          | ¦  «        nd S )Nr%   )r'   r    )r\   s    r!   Ú
_tool_namer_   –   s(   € Ý�4˜ Ñ&Ô&ÐT¸Ð9I­4°©:¬:¨:ÈtÐTr#   Úitemútuple[str | None, str | None]c                ó  — | €dS t          | dd¦  «        }t          | dd¦  «        pg }g }|D ];}t          |dd¦  «        pt          |dd¦  «        }|r|                     |¦  «         Œ<|d                     |¦  «        pdfS )z9Best-effort ``(role, text)`` for a realtime history item.N©NNÚroleÚcontentÚ
transcriptr*   ú )r'   rV   Újoin)r`   rd   re   ÚpartsÚpartr*   s         r!   Ú
_item_textrk   š   sž   € à€|ØˆzÝ�4˜ Ñ&Ô&€DÝ�d˜I tÑ,Ô,Ð2°€GØ€EØð ð ˆÝ�t˜\¨4Ñ0Ô0ÐOµG¸DÀ&È$Ñ4OÔ4OˆØð 	Ø�LŠL˜ÑÔÐøØ�#—(’(˜5‘/”/Ð) TÐ*Ð*r#   Úeventútuple[str | None, str] | Nonec                óÊ   — t          | dd¦  «        }t          |dd¦  «        dk    rdS t          |dd¦  «        pd                     ¦   «         }|sdS 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.
    ÚdataNr<   Ú#input_audio_transcription_completedrf   Ú Úitem_id)r'   Ústrip)rl   ro   rf   s      r!   Úraw_input_transcriptrt   ¨   sx   € õ �5˜& $Ñ'Ô'€DÝˆt�V˜TÑ"Ô"Ð&KÒKÐKØˆtÝ˜$ ¨dÑ3Ô3Ð9°r×@Ò@ÑBÔB€JØð ØˆtÝ�4˜ DÑ)Ô)¨:Ð5Ð5r#   c                óB  — t          | dd¦  «        }t          |dd¦  «        }t          |t          ¦  «        r|                     d¦  «        dk    rdS |                     d¦  «        }t          |t          ¦  «        sdS t	          |                     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.
    ro   Nr<   zresponse.doneÚresponseÚusage)r'   r   r   Úgetr   )rl   ro   Úrawrv   s       r!   Úraw_response_usagerz   ¸   s“   € õ �5˜& $Ñ'Ô'€DÝ
�$˜ Ñ
%Ô
%€CÝ�c�4Ñ Ô ð  C§G¢G¨F¡O¤O°Ò$FÐ$FØˆtØ�wŠw�zÑ"Ô"€HÝ�h¥Ñ%Ô%ð ØˆtÝ$ X§\¢\°'Ñ%:Ô%:Ñ;Ô;Ð;r#   ú)tuple[str | None, str | None, str | None]c                óp   — t          | dd¦  «        }t          |¦  «        \  }}t          |dd¦  «        ||fS )zF``(item_id, role, text)`` for a ``history_added`` event's single item.r`   Nrr   )r'   rk   )rl   r`   rd   r*   s       r!   Úhistory_itemr}   Ë   s=   € å�5˜& $Ñ'Ô'€DÝ˜DÑ!Ô!�J€Dˆ$Ý�4˜ DÑ)Ô)¨4°Ð5Ð5r#   ú/list[tuple[str | None, str | None, str | None]]c                ó¨   — g }t          | dd¦  «        pg D ];}t          |¦  «        \  }}|                     t          |dd¦  «        ||f¦  «         Œ<|S )zK``(item_id, role, text)`` for every item in a ``history_updated`` snapshot.ÚhistoryNrr   )r'   rk   rV   )rl   rW   r`   rd   r*   s        r!   Úhistory_messagesr�   Ò   sg   € à;=€CÝ˜˜y¨$Ñ/Ô/Ð5°2ð Að AˆÝ Ñ%Ô%‰
ˆˆdØ�
Š
•G˜D )¨TÑ2Ô2°D¸$Ð?Ñ@Ô@Ð@Ð@Ø€Jr#   ú tuple[str, dict[str, Any], bool]c                ó  — t          | dd¦  «        pt          | ¦  «        }t          | ¦  «        }t          |t          ¦  «        r|nd|i}||d<   d}|dv r%t          t          | dd¦  «        dd¦  «        |d<   �n|dk    rFt          t          | d	d¦  «        ¦  «        |d	<   t          t          | d
d¦  «        ¦  «        |d
<   d}�nµ|dk    ret          t          | d	d¦  «        ¦  «        |d	<   t          t          | d
d¦  «        ¦  «        |d
<   t          t          | dd¦  «        ¦  «        |d<   �nJ|dk    rt          | dd¦  «        |d<   �n.|dk    r3t          t          | dd¦  «        ¦  «        \  }}||c|d<   |d<   |dk    }nõ|dk    rSt          | dd¦  «        pg }|rt          |d         ¦  «        nd\  }}||c|d<   |d<   t          |¦  «        |d<   |dk    }nœ|dk    rGt          t          | dd¦  «        dd¦  «        |d<   t          t          | dd¦  «        dd¦  «        |d<   nO|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)``.r<   Nr   F©Úagent_startÚ	agent_endÚagentr%   Ú
tool_startr\   Ú	argumentsTÚtool_endÚoutputÚaudio_interruptedrr   Úhistory_addedr`   rd   r*   ÚuserÚhistory_updatedr€   éÿÿÿÿrc   Ú	last_roleÚ	last_textÚlengthÚhandoffÚ
from_agentÚto_agentÚguardrail_trippedÚmessageÚerror)	r'   r    rJ   r   r   r_   r"   rk   r(   )rl   ÚetypeÚdumpedÚpayloadÚinboundrd   r*   r€   s           r!   Údescribe_eventrž   Û   sÕ  € å�E˜6 4Ñ(Ô(Ð7­D°©K¬K€EÝ�E‰]Œ]€FÝ(2°6½4Ñ(@Ô(@ÐW˜f˜fÀwÐPVÐFW€GØ€GˆF�OØ€GàÐ,Ð,Ð,Ý"¥7¨5°'¸4Ñ#@Ô#@À&È$ÑOÔOˆ�ÑÑØ	�,Ò	Ð	Ý$¥W¨U°F¸DÑ%AÔ%AÑBÔBˆ�‰Ý)­'°%¸ÀdÑ*KÔ*KÑLÔLˆ�ÑØˆ‰Ø	�*Ò	Ð	Ý$¥W¨U°F¸DÑ%AÔ%AÑBÔBˆ�‰Ý)­'°%¸ÀdÑ*KÔ*KÑLÔLˆ�ÑÝ&¥w¨u°hÀÑ'EÔ'EÑFÔFˆ�ÑÑØ	Ð%Ò	%Ð	%Ý$ U¨I°tÑ<Ô<ˆ�	ÑÑØ	�/Ò	!Ð	!Ý¥¨¨v°tÑ <Ô <Ñ=Ô=‰
ˆˆdØ+/°Ð(ˆ�‰˜ ™Ø˜&’.ˆˆØ	Ð#Ò	#Ð	#Ý˜% ¨DÑ1Ô1Ð7°RˆØ07ÐI•Z ¨¤Ñ,Ô,Ð,¸\‰
ˆˆdØ59¸4Ð2ˆ�Ñ˜g kÑ2Ý ™LœLˆ�ÑØ˜&’.ˆˆØ	�)Ò	Ð	Ý 'Ý�E˜<¨Ñ.Ô.°¸ñ!
ô !
ˆ�Ñõ &¥g¨e°ZÀÑ&FÔ&FÈÐPTÑUÔUˆ�
ÑÐØ	Ð%Ò	%Ð	%Ý'­°°yÀ$Ñ(GÔ(GÑHÔHˆ�	ÑÐØ	�'Ò	Ð	Ý%¥g¨e°W¸dÑ&CÔ&CÑDÔDˆ�Ñà�'˜7Ð"Ð"r#   ÚsessionúOptional[str]c                ó¼   — t          | dd¦  «        }t          |t          ¦  «        r|pdS dD ].}t          ||d¦  «        }t          |t          ¦  «        r|r|c S Œ/dS )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   )rŸ   r¢   Úattrr%   s       r!   Ú_resolve_modelr¥     sy   € õ �G˜W dÑ+Ô+€EÝ�%�ÑÔð Øˆ}˜ÐØ'ð ð ˆÝ�u˜d DÑ)Ô)ˆÝ�d�CÑ Ô ð 	 Tð 	ØˆKˆKˆKøØˆ4r#   c                  ój   — 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dS ),Ú_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¢   rŸ   r   r©   ú$Optional[Callable[[str, str], None]]r¢   r    r   ÚNonec               ó´   — || _         || _        || _        i | _        t	          ¦   «         | _        t	          ¦   «         | _        d | _        d | _        i | _	        d S r/   )
Ú_traceÚ_on_messageÚ_modelÚ_itemsrU   Ú_emittedÚ	_notifiedÚ_latency_sinceÚ_pending_usageÚ_open_tools)ÚselfrŸ   r©   r¢   s       r!   Ú__init__z_AgentsRealtimeTracer.__init__"  s[   € ð ˆŒØ%ˆÔØˆŒà13ˆŒÝ"%¡%¤%ˆŒÝ/2©u¬uˆŒà,0ˆÔð 6:ˆÔð
 PRˆÔÐÐr#   rl   r   c                óÈ  — | j                              ¦   «         }t          |dd¦  «        }|€dS |dk    r|                      |¦  «         dS |dk    r`t	          |¦  «        x}�|| _        t          |¦  «        }|r5|\  }}|                      |d|fg|¦  «         |                      d¬¦  «         dS |dk    r<|                      t          |¦  «        g|¦  «         |                      d¬¦  «         dS |d	k    r;|                      t          |¦  «        |¦  «         |                      d¬¦  «         dS |d
v rdS |dk    r|                      |¦  «         dS |dk    r|                      ||¦  «         dS t          |¦  «        \  }}	}
|dk    r| j                              d¬¦  «         | j                              |	|||
¬¦  «        5  	 ddd¦  «         dS # 1 swxY w Y   dS )zBObserve one session event: fold history, emit spans, time latency.r<   NÚaudioÚraw_model_eventrŽ   T©Ú	hold_lastr�   r�   r„   rˆ   rŠ   rŒ   )Úwas_interrupted)r%   r�   )r­   Únowr'   Úrecord_first_audiorz   r´   rt   Ú_observe_itemsÚ_flushr}   r�   Ú_start_toolÚ	_end_toolrž   Úadd_turn_metadataÚ
event_span)r¶   rl   Úreceived_atrš   rw   Úrecrr   rf   r%   rœ   r�   s              r!   Úobservez_AgentsRealtimeTracer.observe;  sx  € à”k—o’oÑ'Ô'ˆÝ˜˜v tÑ,Ô,ˆØˆ=ØˆFà�GÒÐØ×#Ò# KÑ0Ô0Ð0ØˆFØÐ%Ò%Ð%Ý+¨EÑ2Ô2Ð2�Ð?Ø&+�Ô#Ý& uÑ-Ô-ˆCØð ,Ø&)Ñ#�˜Ø×#Ò# g¨v°zÐ%BÐ$CÀ[ÑQÔQÐQØ—’ d�Ñ+Ô+Ð+ØˆFØ�OÒ#Ð#Ø×Ò¥¨eÑ!4Ô!4Ð 5°{ÑCÔCÐCØ�KŠK $ˆKÑ'Ô'Ð'ØˆFØÐ%Ò%Ð%Ø×ÒÕ 0°Ñ 7Ô 7¸ÑEÔEÐEØ�KŠK $ˆKÑ'Ô'Ð'ØˆFØÐ0Ð0Ð0ØˆFð �LÒ Ð Ø×Ò˜UÑ#Ô#Ð#ØˆFØ�JÒÐØ�NŠN˜5 +Ñ.Ô.Ð.ØˆFõ "0°Ñ!6Ô!6Ñˆˆg�wØÐ'Ò'Ð'ØŒK×)Ò)¸$Ð)Ñ?Ô?Ð?ð Œ[×#Ò# G¨[¸tÈWÐ#ÑUÔUð 	ð 	Øð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s   ÇGÇGÇGc                ó   — t          t          |dd¦  «        ¦  «        }t          t          |dd¦  «        ¦  «        }| j                             |pddd|i¬¦  «        }| j                             ||fg ¦  «                             |¦  «         dS )z:Open a held-open ``tool`` span for a ``tool_start`` event.r\   Nr‰   )r%   Úrun_typeÚinputs)r_   r'   r"   r­   Ú	open_spanrµ   Ú
setdefaultrV   )r¶   rl   r%   ÚargsÚruns        r!   rÂ   z!_AgentsRealtimeTracer._start_tooll  s•   € å�' %¨°Ñ6Ô6Ñ7Ô7ˆÝ�' %¨°dÑ;Ô;Ñ<Ô<ˆØŒk×#Ò#Ø�˜ØØ Ð&ð $ñ 
ô 
ˆð
 	Ô×#Ò# T¨4 L°"Ñ5Ô5×<Ò<¸SÑAÔAÐAÐAÐAr#   rÆ   r   c           
     ó  — t          t          |dd¦  «        ¦  «        }t          t          |dd¦  «        ¦  «        }t          t          |dd¦  «        ¦  «        }| j                             ||f¦  «        }|rA|                     d¦  «        }|s
| j        ||f= | j                             |d|i¬¦  «         dS | j                             |||dœ||pdddd|id|i¬	¦  «        5  	 ddd¦  «         dS # 1 swxY w Y   dS )
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.
        r\   Nr‰   r‹   r   )Úoutputs)r\   r‰   r‹   F)r%   rÊ   r�   rË   rÑ   )	r_   r'   r"   rµ   rx   Úpopr­   Ú
close_spanrÅ   )r¶   rl   rÆ   r%   rÎ   r‹   ÚqueuerÏ   s           r!   rÃ   z_AgentsRealtimeTracer._end_toolw  so  € õ �' %¨°Ñ6Ô6Ñ7Ô7ˆÝ�' %¨°dÑ;Ô;Ñ<Ô<ˆÝ�G E¨8°TÑ:Ô:Ñ;Ô;ˆØÔ ×$Ò$ d¨D \Ñ2Ô2ˆØð 	Ø—)’)˜A‘,”,ˆCØð 3ØÔ$ d¨D \Ð2ØŒK×"Ò" 3°¸6Ð0BÐ"ÑCÔCÐCØˆFØŒ[×#Ò#Ø¨¸Ð?Ð?ØØ�˜ØØØ Ð&Ø˜vÐ&ð $ñ 
ô 
ð 		ð 		ð ð		ð 		ð 		ñ 		ô 		ð 		ð 		ð 		ð 		ð 		ð 		ð 		øøøð 		ð 		ð 		ð 		ð 		ð 		s   Ã%C4Ã4C8Ã;C8c                óè   — |                       d¬¦  «         | j                             ¦   «         D ](}|D ]#}d|_        | j                             |¦  «         Œ$Œ)| j                             ¦   «          dS )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“  s‡   € ð 	�Š˜eˆÑ$Ô$Ð$ØÔ%×,Ò,Ñ.Ô.ð 	,ð 	,ˆEØð ,ð ,�ØL�”	Ø”×&Ò& sÑ+Ô+Ð+Ð+ð,ð 	Ô×ÒÑ Ô Ð Ð Ð r#   Úseqúlist[tuple]c                óP  — |D ]¢\  }}}|sŒ	|| j         vr<|dk    r6|                      d¬¦  «         | j                             ¦   «          || _        | j                              |¦  «        }|€||dœ| j         |<   n|r||d<   |r||d<   |dv r|r|                      ||¦  «         Œ£dS )	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)rd   r*   rd   r*   ©rŽ   Ú	assistant)r°   rÁ   r­   Ú
start_turnr³   rx   Ú_notify)r¶   rÙ   rÆ   Úiidrd   r*   Úcurs          r!   rÀ   z$_AgentsRealtimeTracer._observe_items¡  sê   € ð  #ð 	)ð 	)‰OˆC��tØð ØØ˜$œ+Ð%Ð%¨$°&ª.¨.Ø—’ e�Ñ,Ô,Ð,Ø”×&Ò&Ñ(Ô(Ð(Ø&1�Ô#Ø”+—/’/ #Ñ&Ô&ˆCØˆ{Ø,0¸$Ð#?Ð#?�”˜CÑ Ð àð 'Ø"&�C˜‘KØð 'Ø"&�C˜‘KØÐ,Ð,Ð,°Ð,Ø—’˜T 4Ñ(Ô(Ð(øð!	)ð 	)r#   r¼   r   c                óæ   — t          | j        ¦  «        }|rt          |¦  «        dz
  nt          |¦  «        }|dt          d|¦  «        …         D ] }|| j        vr|                      |¦  «         Œ!dS )z Emit not-yet-emitted items in order.

        Optionally holds back the last (still-streaming) item until it is
        superseded or the session ends.
        rF   Nr   )r   r°   r(   Úmaxr±   Ú_record_item)r¶   r¼   ÚidsÚcutoffrà   s        r!   rÁ   z_AgentsRealtimeTracer._flushº  s   € õ �4”;ÑÔˆØ!*Ð8•�S‘”˜A‘�µ°C±´ˆØÐ'�˜Q ™œÐ'Ô(ð 	'ð 	'ˆCØ˜$œ-Ð'Ð'Ø×!Ò! #Ñ&Ô&Ð&øð	'ð 	'r#   c                óŒ   — | j         �<| j                             t          || j         z
  dz  ¦  «        ¬¦  «         d| _         dS dS )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Æ  s_   € àÔÐ*ØŒK×)Ò)Ý*/Ø  4Ô#6Ñ6¸$Ñ>ñ+ô +ð *ñ ô ð ð
 #'ˆDÔÐÐð +Ð*r#   rd   r]   r*   c                óž   — | j         �|r|sdS ||f| j        v rdS | j                             ||f¦  «         |                       ||¦  «         dS )zCSend one finalized transcript line to the on_message callback once.N)r®   r²   Úadd)r¶   rd   r*   s      r!   rß   z_AgentsRealtimeTracer._notifyÐ  sf   € àÔÐ#¨4Ð#°tÐ#ØˆFØ�$ˆ<˜4œ>Ð)Ð)ØˆFØŒ×Ò˜D $˜<Ñ(Ô(Ð(Ø×Ò˜˜tÑ$Ô$Ð$Ð$Ð$r#   rà   r   c           	     ó~  — | j         |         d         }| j         |         d         pd                     ¦   «         }|dvr| j                             |¦  «         dS |sdS | j                             |¦  «         |                      ||¦  «         | j                             ||¦  «         |dk    rY| j                             |d|dœ| j                             ¦   «         dd	d|d
œ¬¦  «        5  	 ddd¦  «         dS # 1 swxY w Y   dS | j         	                    d|d
œ| j
        d| j        dœ¬¦  «         d| _
        dS )z:Emit one message span for a finalized history item (once).rd   r*   rq   rÜ   NrŽ   )rr   rd   re   Úuser_messageT)rd   re   )r%   r�   rË   rÝ   Úopenai)Úls_providerÚls_model_name)rÑ   Úusage_metadataÚmetadata)r°   rs   r±   rë   rß   r­   Úadd_messagerÅ   r¾   Ú
record_llmr´   r¯   )r¶   rà   rd   r*   s       r!   rä   z"_AgentsRealtimeTracer._record_itemÙ  s¶  € àŒ{˜3Ô Ô'ˆØ”˜CÔ  Ô(Ð.¨B×5Ò5Ñ7Ô7ˆØÐ,Ð,Ð,ØŒM×Ò˜cÑ"Ô"Ð"ØˆFØð 	ØˆFØŒ×Ò˜#ÑÔÐØ�Š�T˜4Ñ Ô Ð ØŒ×Ò  dÑ+Ô+Ð+Ø�6Š>ˆ>Ø”×'Ò'Ø¨¸DÐAÐAØ”—’Ñ!Ô!Ø#ØØ &°4Ð8Ð8ð (ñ ô ð ð ð ðð ð ñ ô ð ð ð ð ð ð ð øøøð ð ð ð ð ð ð ŒK×"Ò"Ø!,¸Ð>Ð>Ø#Ô2Ø)1ÀDÄKÐPÐPð #ñ ô ð ð
 #'ˆDÔÐÐs   Ã-C<Ã<D ÄD )rŸ   r   r©   rª   r¢   r    r   r«   )rl   r   r   r«   )rl   r   rÆ   r   r   r«   )r   r«   )rÙ   rÚ   rÆ   r   r   r«   )r¼   r   r   r«   )rÆ   r   r   r«   )rd   r]   r*   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§     s  € € € € € ðð ð <@Ø#ðRð Rð Rð Rð Rð Rð2/ð /ð /ð /ðb	Bð 	Bð 	Bð 	Bðð ð ð ð8!ð !ð !ð !ð)ð )ð )ð )ð2
'ð 
'ð 
'ð 
'ð'ð 'ð 'ð 'ð%ð %ð %ð %ð'ð 'ð 'ð 'ð 'ð 'r#   r§   c                  óR   — 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d&S )-Ú_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.
    rŸ   r   Ú	thread_idr    Úsample_rater   Úproject_nameÚtagsúOptional[list[str]]rò   úOptional[dict[str, Any]]r©   rª   Úmax_audio_secondsúOptional[float]ÚclientúOptional[Client]Úreplicasú Optional[Sequence[WriteReplica]]r   r«   c       	        ó
  — || _         |pt          t          j        ¦   «         ¦  «        | _        || _        || _        || _        || _        || _	        || _
        |	| _        |
| _        d | _        d | _        d | _        d | _        d S r/   )Ú_sessionr   ÚuuidÚuuid4Ú
_thread_idÚ_sample_rateÚ_project_nameÚ_tagsÚ	_metadatar®   Ú_max_audio_secondsÚ_clientÚ	_replicasr­   Ú_tracerÚ_ctxÚ_aiter)r¶   rŸ   rü   rý   rþ   rÿ   rò   r©   r  r  r  s              r!   r·   z_TracedRealtimeSession.__init__   sƒ   € ð   ˆŒØ#Ð8¥s­4¬:©<¬<Ñ'8Ô'8ˆŒØ'ˆÔØ)ˆÔØˆŒ
Ø!ˆŒØ%ˆÔØ"3ˆÔØˆŒØ!ˆŒð /3ˆŒØ8<ˆŒØˆŒ	ØˆŒˆˆr#   r%   r   c                óT   — t          t                               | d¦  «        |¦  «        S )Nr	  )r'   ÚobjectÚ__getattribute__)r¶   r%   s     r!   Ú__getattr__z"_TracedRealtimeSession.__getattr__!  s"   € Ý•v×.Ò.¨t°ZÑ@Ô@À$ÑGÔGÐGr#   c              ƒ  óî  K  — | j                              ¦   «         ƒ d {V —† 	 t          | j        | j        | j        | j        | j        | j        | j	        | j
        dt          d¦  «        ¬¦
  «
        }|| _        t          d| j        i| j        | j        | j
        ¬¦  «        }|                     ¦   «          || _        t!          || j        t%          | j         ¦  «        ¬¦  «        | _        nŠ# t(          $ r} | j        �N	  | j        j        t-          j        ¦   «         Ž  n,# t0          $ r t2                               dd¬	¦  «         Y nw xY w | j         j        t-          j        ¦   «         Ž ƒ d {V —† ‚ w xY w| S )
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__$  sº  è è € ØŒm×&Ò&Ñ(Ô(Ð(Ð(Ð(Ð(Ð(Ð(Ð(ð$	Ý!Øœ/Ø Ô-Ø!Ô/Ø”ZØœØ"&Ô"9Ø”|ØœØ4Ý$7¸Ñ$HÔ$Hðñ ô ˆEð  ˆDŒKÝ!Ø% t¤Ð7Ø”ZØ!Ô/Øœð	ñ ô ˆCð �MŠM‰OŒOˆOØˆDŒIÝ0Ø $Ô"2½.ÈÌÑ:WÔ:Wðñ ô ˆDŒLˆLøõ ð 	ð 	ð 	ØŒyÐ$ðØ&�D”IÔ&­¬©¬Ð7Ð7Ð7øÝ ð ð ð Ý—L’Lð(à!%ð !ñ ô ð ð ð ðøøøð *�$”-Ô)­3¬<©>¬>Ð:Ð:Ð:Ð:Ð:Ð:Ð:Ð:Øð	øøøð ˆs0   £CC+ Ã+E2Ã= DÄE2Ä&EÅE2ÅEÅ+E2Úexc_typeÚexcÚtbc              ƒ  óú  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| j                             |||¦  «        ƒ d {V —†S )Nz: z)voice tracing: failed to finalize sessionTr  )r  rØ   r­   rõ   rÏ   r™   Úfinalizer%  r&  Úwarningr  r#  r	  r(  )r¶   r+  r,  r-  s       r!   r(  z _TracedRealtimeSession.__aexit__P  s$  è è € ð	5ØŒ|Ð'Ø”×*Ò*Ñ,Ô,Ð,ØŒ{Ð&Ø�?Ø/7Ô/@Ð,IÐ,IÀCÐ,IÐ,I�D”K”OÔ)Ø”×$Ò$Ñ&Ô&Ð&øøÝð 	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ð %øøøà”]×,Ò,¨X°s¸BÑ?Ô?Ð?Ð?Ð?Ð?Ð?Ð?Ð?s*   „AA" Á!B2 Á"&BÂB2 Â
BÂB2 Â2&Cc                óB   — | j                              ¦   «         | _        | S r/   )r	  Ú	__aiter__r  )r¶   s    r!   r2  z _TracedRealtimeSession.__aiter__b  s   € Ø”m×-Ò-Ñ/Ô/ˆŒØˆr#   c              ƒ  óÒ   K  — | j         }|€ | j                             ¦   «         }|| _         |                     ¦   «         ƒ d {V —†}| j        �t          | j        j        |¦  «         |S r/   )r  r	  r2  Ú	__anext__r  r	   rÈ   )r¶   Úaiterrl   s      r!   r4  z _TracedRealtimeSession.__anext__f  so   è è € Ø”ˆØˆ=Ø”M×+Ò+Ñ-Ô-ˆEØˆDŒKØ—o’oÑ'Ô'Ð'Ð'Ð'Ð'Ð'Ð'ˆØŒ<Ð#Ý˜4œ<Ô/°Ñ7Ô7Ð7Øˆr#   ÚpcmrM   c                ó|   — | j         �4| j                              | j                              ¦   «         |¦  «         dS dS )zCRecord a chunk of user (mic) PCM16 for the stereo conversation WAV.N)r­   Úrecord_userr¾   ©r¶   r6  s     r!   Úrecord_user_audioz(_TracedRealtimeSession.record_user_audiop  s<   € àŒ;Ð"ØŒK×#Ò# D¤K§O¢OÑ$5Ô$5°sÑ;Ô;Ð;Ð;Ð;ð #Ð"r#   c                ó|   — | j         �4| j                              | j                              ¦   «         |¦  «         dS dS )zGRecord a chunk of agent (played) PCM16 for the stereo conversation WAV.N)r­   Úrecord_agentr¾   r9  s     r!   Úrecord_agent_audioz)_TracedRealtimeSession.record_agent_audiou  s<   € àŒ;Ð"ØŒK×$Ò$ T¤[§_¢_Ñ%6Ô%6¸Ñ<Ô<Ð<Ð<Ð<ð #Ð"r#   N)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   )r6  rM   r   r«   )rõ   rö   r÷   rø   r·   r  r   r(  r2  r4  r:  r=  rù   r#   r!   rû   rû   ÷  sÈ   € € € € € ðð ð ð  ð  ð  ðBHð Hð Hð Hð*ð *ð *ð *ðX@ð @ð @ð @ð$ð ð ð ðð ð ð ð<ð <ð <ð <ð
=ð =ð =ð =ð =ð =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  c       	        ó4   — 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@  {  s:   € õR "ØØØØ!ØØØØ+ØØðñ ô ð r#   )r   r   r   r   )r   r   r   r,   )r   r   r@   r   rA   rB   r   r   )r\   r   r   r]   )r`   r   r   ra   )rl   r   r   rm   )rl   r   r   r,   )rl   r   r   r{   )rl   r   r   r~   )rl   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û   )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_RATErP   rS   r)   r"   r+   r?   Ú	frozensetrJ   r_   rk   rt   rz   r}   r�   rž   r¥   r§   rû   r@  rù   r#   r!   ú<module>rO     s  ððð ðB #Ð "Ð "Ð "Ð "Ð "à Ð Ð Ð Ø €€€Ø 
€
€
€
Ø €€€Ø 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Ñ	$Ô	$€ð Ð à€
Ø€
Ø€	ðð ð ð ðHð Hð Hð Hðð ð ð ð  %&¸i¸i¹k¼kð 'ð 'ð 'ð 'ð 'ðTUð Uð Uð Uð+ð +ð +ð +ð6ð 6ð 6ð 6ð <ð <ð <ð <ð&6ð 6ð 6ð 6ðð ð ð ð(#ð (#ð (#ð (#ðVð ð ð ð"]'ð ]'ð ]'ð ]'ð ]'ñ ]'ô ]'ð ]'ð@A=ð A=ð A=ð A=ð A=ñ A=ô A=ð A=ðN  $Ø*Ø"&Ø $Ø)-Ø7;Ø)BØ#Ø15ð4ð 4ð 4ð 4ð 4ð 4ð 4ð 4r#   