ó
    üÞ j­:  ã                  ó:  • S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSKrSSK	J
r
  SSKJrJrJr  SSKJr  SSKJr  \(       a  SSKJrJr  \R,                  " \5      rS	rSrS	rS
rSrSrSS jrSS jr  " S S5      r!Sr"SS jr#S r$ " S S5      r% " S S5      r&g)a  TCP tunnel for accessing services running inside sandboxes.

Establishes a WebSocket connection to the daemon's ``/tunnel`` endpoint,
runs a yamux multiplexing session on top, and forwards local TCP connections
through yamux streams to the target port inside the sandbox.
é    )ÚannotationsN)ÚMapping)ÚTYPE_CHECKINGÚAnyÚOptional)Úmerge_headers)ÚWS_OPEN_TIMEOUT)ÚYamuxSessionÚYamuxStreamé   é   é   z>BHc                ób   • U R                  [        R                  " [        [        U5      5        g)zAWrite the 3-byte connect header on a freshly opened yamux stream.N)ÚwriteÚstructÚpackÚ_CONNECT_HEADER_FMTÚPROTOCOL_VERSION)ÚstreamÚports     ÚS/var/www/html/gaurav/venv/lib/python3.13/site-packages/langsmith/sandbox/_tunnel.pyÚ_write_connect_headerr   )   s   € à
‡L�L”—’Ô0Ô2BÀDÓIÕJó    c                óR   • U R                  S5      nU(       d  [        S5      eUS   $ )z0Read the 1-byte status response from the daemon.r   z'tunnel: connection closed before statusr   )ÚreadÚConnectionError)r   Údatas     r   Ú_read_statusr   .   s'   € à�;‰;�q‹>€DÞÜÐGÓHÐHØ�‰7€Nr   c                  ó@   • \ rS rSrSrS	S jrS
S jrSS jrSS jrSr	g)Ú
_WSAdapteré;   zúAdapts the ``websockets`` message API to a byte-stream interface.

yamux requires a plain read/write/close byte stream.  WebSocket is
message-based, so this adapter buffers partially consumed messages on
reads and sends one binary message per write.
c                ób   • Xl         [        5       U l        [        R                  " 5       U l        g ©N)Ú_wsÚ	bytearrayÚ_bufÚ	threadingÚLockÚ_write_lock)ÚselfÚwss     r   Ú__init__Ú_WSAdapter.__init__C   s   € ØŒÜ“KˆŒ	Ü$Ÿ>š>Ó+ˆÕr   c                óp  • [        U R                  5      U:  au  U R                  R                  5       n[	        U[
        5      (       a  UR                  5       nU R                  R                  U5        [        U R                  5      U:  a  Mu  [        U R                  S U 5      nU R                  S U2	 U$ r#   )	Úlenr&   r$   ÚrecvÚ
isinstanceÚstrÚencodeÚextendÚbytes)r*   ÚnÚmsgÚresults       r   r   Ú_WSAdapter.readH   s‡   € Ü�$—)‘)‹n˜qÓ Ø—(‘(—-‘-“/ˆCÜ˜#œs×#Ñ#Ø—j‘j“l�Ø�I‰I×Ñ˜SÔ!ô	 �$—)‘)‹n˜qÕ ô �t—y‘y  !�}Ó%ˆØ�I‰I�b�q�bˆMØˆr   c                óš   • U R                      U R                  R                  U5        S S S 5        [        U5      $ ! , (       d  f       N= fr#   )r)   r$   Úsendr/   )r*   r   s     r   r   Ú_WSAdapter.writeS   s3   € Ø×ÓØ�H‰H�M‰M˜$Ô÷ ä�4‹yÐ÷ Õús	   �<¼
A
c                óZ   •  U R                   R                  5         g ! [         a     g f = fr#   )r$   ÚcloseÚ	Exception©r*   s    r   r>   Ú_WSAdapter.closeX   s'   € ð	Ø�H‰H�N‰NÕøÜó 	Ùð	ús   ‚ �
*©*)r&   r)   r$   N)r+   r   ÚreturnÚNone)r6   ÚintrB   r5   )r   r5   rB   rD   ©rB   rC   )
Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r,   r   r   r>   Ú__static_attributes__© r   r   r    r    ;   s   † ñô,ô
	ô÷
r   r    i @  c                ó0  ^ ^^• [         R                  " 5       mSUU U4S jjnSUU U4S jjn[         R                  " USS9n[         R                  " USS9nUR                  5         UR                  5         TR	                  5          T R                  5          TR                  [        R                  5         TR                  5         UR                  SS9  UR                  SS9  g! [         a     N\f = f! [         a     NLf = f! [         a     NKf = f)	z:Copy data bidirectionally until one side closes or errors.c                 óÔ   >•   TR                  [        5      n U (       d  OTR                  U 5        M0  TR	                  5         g ! [         a     Nf = f! TR	                  5         f = fr#   )r   Ú_BRIDGE_BUF_SIZEÚsendallr?   Úset©r   Údoner   Útcp_conns    €€€r   Ú_stream_to_tcpÚ_bridge.<locals>._stream_to_tcpj   s^   ø€ ð		ØØ—{‘{Ô#3Ó4�ÞØØ× Ñ  Ô&ñ	 ð �H‰H�Jøô ó 	Ùð	ûð �H‰H�Júó-   ƒA  A ¡A Á
AÁA ÁAÁA ÁA'c                 óÔ   >•   TR                  [        5      n U (       d  OTR                  U 5        M0  TR	                  5         g ! [         a     Nf = f! TR	                  5         f = fr#   )r0   rO   r   r?   rQ   rR   s    €€€r   Ú_tcp_to_streamÚ_bridge.<locals>._tcp_to_streamv   s\   ø€ ð		ØØ—}‘}Ô%5Ó6�ÞØØ—‘˜TÔ"ñ	 ð �H‰H�Jøô ó 	Ùð	ûð �H‰H�JúrW   T)ÚtargetÚdaemoné   )ÚtimeoutNrE   )r'   ÚEventÚThreadÚstartÚwaitr>   r?   ÚshutdownÚsocketÚ	SHUT_RDWRÚOSErrorÚjoin)r   rT   rU   rY   Út1Út2rS   s   ``    @r   Ú_bridgerj   f   sò   ú€ ä�?Š?Ó€D÷
ñ 
÷
ñ 
ô 
×	Ò	 ¸Ñ	=€BÜ	×	Ò	 ¸Ñ	=€BØ‡H�H„JØ‡H�H„Jà‡I�I„KðØ�‰ŒðØ×Ñœ&×*Ñ*Ô+ðØ�‰Ôð ‡G�G�A€GÑØ‡G�G�A€GÒøô ó Ùðûô ó Ùðûô ó Ùðús6   ÂC( ÂC8 Â9D Ã(
C5Ã4C5Ã8
DÄDÄ
DÄDc                 óH   •  SSK Jn   U $ ! [         a    [        S5      Sef = f)z5Import websockets sync client or raise a clear error.r   )Úconnectz„TCP tunnel requires the 'websockets' package, which ships with langsmith by default. Reinstall with: pip install --upgrade langsmithN)Úwebsockets.sync.clientrl   ÚImportError)Ú
ws_connects    r   Ú_ensure_websocketsrp   Ÿ   s6   € ð	Ý@àÐøÜó Üð.ó
ð ð		ðús   ‚
 Š!c                  óÜ   • \ rS rSrSrSrSrSSSS.             SS	 jjr\SS
 j5       r	\SS j5       r
SS jrSS jrSS jrSS jrSS jrSS jrSS jrSS jrSS jrSS jrSrg)ÚTunnelé­   aÚ  TCP tunnel to a port inside a sandbox.

Opens a local TCP listener and forwards each accepted connection through
a yamux-multiplexed WebSocket to the daemon, which dials the target port
inside the sandbox.

Typically used as a context manager::

    with sandbox.tunnel(remote_port=5432) as t:
        conn = psycopg2.connect(host="127.0.0.1", port=t.local_port)

Or with explicit lifecycle::

    t = sandbox.tunnel(remote_port=5432)
    # ... use tunnel ...
    t.close()
ç      à?g       @r   r   N©Ú
local_portÚmax_reconnectsÚheadersc               ó
  • Xl         X l        X`l        X0l        U=(       d    UU l        U R                  U l        XPl        S U l        S U l        S U l	        S U l
        [        R                  " 5       U l        SU l        SU l        g )NF)Ú_dataplane_urlÚ_api_keyÚ_headersÚ_remote_portÚ_requested_local_portÚ_local_portÚ_max_reconnectsr$   Ú_yamuxÚ_server_socketÚ_accept_threadr'   r(   Ú_reconnect_lockÚ_closedÚ_started©r*   Údataplane_urlÚapi_keyÚremote_portrv   rw   rx   s          r   r,   ÚTunnel.__init__Ã   sv   € ð ,ÔØŒØŒØ'ÔØ%/×%>°;ˆÔ"Ø×5Ñ5ˆÔØ-ÔàˆŒØ.2ˆŒØ7;ˆÔØ:>ˆÔÜ(Ÿ~š~Ó/ˆÔØˆŒØˆ�r   c                ó   • U R                   $ )z&Local port the tunnel is listening on.)r   r@   s    r   rv   ÚTunnel.local_portÝ   s   € ð ×ÑÐr   c                ó   • U R                   $ )z4Port inside the sandbox that the tunnel connects to.)r}   r@   s    r   rŠ   ÚTunnel.remote_portâ   s   € ð × Ñ Ð r   c                ó   • U $ r#   rL   r@   s    r   Ú	__enter__ÚTunnel.__enter__é   s   € Øˆr   c                ó$   • U R                  5         g r#   )r>   )r*   Úargss     r   Ú__exit__ÚTunnel.__exit__ì   s   € Ø�
‰
�r   c                ó–   • U R                   (       a  g SU l          U R                  5         g ! [         a    U R                  5         e f = f)NT)r†   Ú	_do_startr?   r>   r@   s    r   Ú_startÚTunnel._startñ   s=   € Ø�=�=ØØˆŒð	Ø�N‰NÕøÜó 	Ø�J‰JŒLØð	ús	   ›, ¬Ac                óš  • U R                  5         [        R                  " [        R                  [        R                  5      U l        U R                  R                  [        R                  [        R                  S5        U R                  nUS:w  aw  [        R                  " [        R                  [        R                  5      n UR                  S5        UR                  SU45        UR                  5         [        SU S35      eU R                  R!                  SU R                  45        U R                  R#                  S	5        U R                  R%                  5       S   U l        [(        R*                  " U R,                  S
SS9U l        U R.                  R1                  5         g ! [         a     OH[         a<  nS[        U5      ;   a   S nAO+S[        U5      R                  5       ;   a  e  S nAOS nAff = f UR                  5         GN! [         a     GNf = f!  UR                  5         f ! [         a     f f = f= f)Nr   r   rt   z	127.0.0.1zPort zE is already in use by another service. Choose a different local_port.zConnection refusedzalready in useé€   Tztunnel-accept)r[   r\   Úname)Ú_connectrd   ÚAF_INETÚSOCK_STREAMr‚   Ú
setsockoptÚ
SOL_SOCKETÚSO_REUSEADDRr~   Ú
settimeoutrl   r>   rf   ÚConnectionRefusedErrorr2   ÚlowerÚbindÚlistenÚgetsocknamer   r'   r`   Ú_accept_looprƒ   ra   )r*   r   ÚprobeÚes       r   r˜   ÚTunnel._do_startü   sÎ  € Ø�‰Œä$Ÿmšm¬F¯N©N¼F×<NÑ<NÓOˆÔØ×Ñ×&Ñ&¤v×'8Ñ'8¼&×:MÑ:MÈqÔQð
 ×)Ñ)ˆØ�1‹9Ü—M’M¤&§.¡.´&×2DÑ2DÓEˆEðØ× Ñ  Ô%Ø—‘˜{¨DÐ1Ô2Ø—‘”ÜØ˜D˜6ð "5ð 6óð ð& 	×Ñ× Ñ  +¨t×/IÑ/IÐ!JÔKØ×Ñ×"Ñ" 3Ô'Ø×.Ñ.×:Ñ:Ó<¸QÑ?ˆÔä'×.Ò.Ø×$Ñ$¨T¸ñ
ˆÔð 	×Ñ×!Ñ!Õ#øô- *ó ÙÜó Ø'¬3¨q«6Ó1ÜØ%¬¨Q«¯©«Ó7ØäûðúðØ—K‘K–MøÜó ÚðûðØ—K‘K•MøÜó Ùðýsy   ÃAF/ Æ/
H Æ9H' Æ;	H ÇG;ÇH' ÇG;Ç6H' Ç;H È H' ÈH È
H$È#H$È'I
È)H:È9I
È:
IÉI
ÉIÉI
c                ó€  • SSK Jn  U R                  nU(       a   UR                  5         [        5       nU R                  5       n[        U R                  (       a  SU R                  0OSU R                  5      nU" UU[        SSS9U l        [        U R                  5      nU" U5      U l        g! [         a     N‘f = f)z:Establish (or re-establish) the WebSocket + yamux session.r   )r
   z	X-Api-KeyNr]   )Úadditional_headersÚopen_timeoutÚclose_timeoutÚping_interval)Úlangsmith.sandbox._yamuxr
   r�   r>   r?   rp   Ú_build_ws_urlr   r{   r|   r	   r$   r    )r*   r
   Ú	old_yamuxro   Úws_urlrx   Úadapters          r   rž   ÚTunnel._connect(  sª   € å9à—K‘Kˆ	ÞðØ—‘Ô!ô (Ó)ˆ
Ø×#Ñ#Ó%ˆÜØ,0¯M¯Mˆ[˜$Ÿ-™-Ñ(¸tØ�M‰Mó
ˆñ
 ØØ&Ü(ØØñ
ˆŒô ˜TŸX™XÓ&ˆÙ" 7Ó+ˆ�øô' ó Ùðús   ›B0 Â0
B=Â<B=c                ó   • SSK Jn  U R                  (       a'  U R                  R                  (       d  U R                  $ U R                     U R                  (       a0  U R                  R                  (       d  U R                  sSSS5        $ Sn[        U R                  5       HB  n U R                  5         [        R                  SUS-   5        U R                  s  sSSS5        $    U" SU R                   S35      Ue! [         aa  nUnX0R                  S-
  :  aB  [        U R                  SU-  -  U R                  5      n[        R                  " U5         SnAM½   SnAMÃ  SnAff = f! , (       d  f       g= f)	z4Return a live yamux session, reconnecting if needed.r   )ÚTunnelErrorNz tunnel: reconnected (attempt %d)r   r   ztunnel: reconnect failed after z	 attempts)Úlangsmith.sandbox._exceptionsrº   r�   Ú	is_closedr„   Úranger€   rž   ÚloggerÚdebugr?   ÚminÚ_BACKOFF_BASEÚ_BACKOFF_MAXÚtimeÚsleep)r*   rº   Úlast_errÚattemptÚexcÚdelays         r   Ú_ensure_sessionÚTunnel._ensure_sessionE  s-  € å=à�;�;˜tŸ{™{×4×4Ø—;‘;Ðà×!Ó!Ø�{�{ 4§;¡;×#8×#8Ø—{‘{÷ "Ñ!ð -1ˆHÜ  ×!5Ñ!5Ö6�ð*Ø—M‘M”OÜ—L‘LÐ!CÀWÈqÁ[ÔQØŸ;™;Ñ&÷ "Ñ!ñ
 7ñ Ø1°$×2FÑ2FÐ1GÀyÐQóàðøô !ó *Ø"�HØ×!5Ñ!5¸Ñ!9Ó9Ü #Ø ×.Ñ.°!°W±*Ñ=Ø ×-Ñ-ó!˜ô Ÿ
š
 5×)Ò)õ :ûð*ú÷ "Õ!úsC   Á8E/ÂE/Â(4DÃE/Ã(E/Ä
E,ÄAE'ÅE/Å'E,Å,E/Å/
E=c                ó  • U R                   (       a  gSU l         U R                  (       a   U R                  R                  5         U R                  (       a  U R                  R                  5         gg! [         a     N9f = f)z.Shut down the tunnel, closing all connections.NT)r…   r‚   r>   rf   r�   r@   s    r   r>   ÚTunnel.closec  se   € à�<�<ØØˆŒà××ðØ×#Ñ#×)Ñ)Ô+ð �;�;Ø�K‰K×ÑÕð øô ó Ùðús   ¬A3 Á3
B Á?B c                ó  • U R                   (       da   U R                  R                  5       u  p[        R
                  " U R                  U4SSS9R                  5         U R                   (       d  M`  g g ! [         a     g f = f)NTztunnel-bridge)r[   r”   r\   r�   )r…   r‚   Úacceptrf   r'   r`   Ú_handle_connra   )r*   ÚconnÚ_s      r   rª   ÚTunnel._accept_loopt  sp   € Ø—,—,ðØ×-Ñ-×4Ñ4Ó6‘�ô ×ÒØ×(Ñ(Ø�WØØ$ñ	÷
 ‰eŒgð —,—,“,øô ó Ùðús   “A4 Á4
BÂ Bc                ó¸  •  U R                  5       nUR                  5       n[        X0R                  5        [	        U5      nU[
        :X  a  [        X15        g UR                  5         UR                  5         U[        :X  a!  [        R                  SU R                  5        g U[        :X  a!  [        R                  SU R                  5        g U[        :X  a  [        R                  S[        5        g [        R                  SU5        g ! [         aE  n[        R                  SU5         UR                  5          S nAg ! [          a      S nAg f = fS nAff = f)Nz%tunnel: port %d not allowed by daemonz3tunnel: nothing listening on port %d inside sandboxz.tunnel: protocol version mismatch (client v%d)ztunnel: unknown status %dz$tunnel: connection handler error: %s)rÉ   Úopen_streamr   r}   r   Ú	STATUS_OKrj   r>   ÚSTATUS_PORT_NOT_ALLOWEDr¾   ÚwarningÚSTATUS_DIAL_FAILEDÚSTATUS_UNSUPPORTED_VERSIONr   r?   r¿   rf   )r*   rT   Úsessionr   ÚstatusrÇ   s         r   rÏ   ÚTunnel._handle_conn�  s  € ð$	Ø×*Ñ*Ó,ˆGØ×(Ñ(Ó*ˆFÜ! &×*;Ñ*;Ô<Ü! &Ó)ˆFàœÓ"Ü˜Ô)Øà�L‰LŒNØ�N‰NÔàÔ0Ó0Ü—‘Ø;Ø×%Ñ%õð Ô-Ó-Ü—‘ØIØ×%Ñ%õð Ô5Ó5Ü—‘ØDÜ$õô
 —‘Ð:¸FÕCøäó 	Ü�L‰LÐ?ÀÔEðØ—‘× Ñ øÜó Ýðþð		úsO   ‚AD
 ÁA
D
 Â#*D
 Ã$D
 Ã3D
 Ä

EÄEÄ+E Å 
EÅ
EÅEÅEÅEc                ó†   • U R                   R                  S5      nUR                  SS5      R                  SS5      nU S3$ )NÚ/zhttps://zwss://zhttp://zws://z/tunnel)rz   ÚrstripÚreplace)r*   Úurls     r   r´   ÚTunnel._build_ws_url¨  sA   € Ø×!Ñ!×(Ñ(¨Ó-ˆØ�k‰k˜* hÓ/×7Ñ7¸	À7ÓKˆØ��gˆÐr   )rƒ   r{   r…   rz   r|   r   r€   r„   r}   r~   r‚   r†   r$   r�   ©rˆ   r2   r‰   zOptional[str]rŠ   rD   rv   rD   rw   rD   rx   zOptional[Mapping[str, str]]rB   rC   ©rB   rD   )rB   rr   ©r”   ÚobjectrB   rC   rE   )rB   r
   )rT   úsocket.socketrB   rC   )rB   r2   )rF   rG   rH   rI   rJ   rÁ   rÂ   r,   Úpropertyrv   rŠ   r‘   r•   r™   r˜   rž   rÉ   r>   rª   rÏ   r´   rK   rL   r   r   rr   rr   ­   sÃ   † ñð$ €MØ€Lð ØØ/3ñàðð ðð ð	ð ðð ðð -ðð 
õð4 ó ó ð ð ó!ó ð!ôôô
	ô*$ôX,ô:ô< ô"ô%÷Nr   rr   c                  óŽ   • \ rS rSrSrSSSS.             SS jjr\SS j5       r\SS	 j5       rSS
 jr	SS jr
SS jrSrg)ÚAsyncTunneli³  a[  Async wrapper around :class:`Tunnel`.

The underlying tunnel runs in background threads (TCP listener + bridges);
async context-manager methods delegate to the sync tunnel via the event
loop's executor.

Usage::

    async with await sandbox.tunnel(remote_port=5432) as t:
        conn = await asyncpg.connect(host="127.0.0.1", port=t.local_port)
r   r   Nru   c          	     ó*   • [        UUUUUUS9U l        g )Nru   )rr   Ú_tunnelr‡   s          r   r,   ÚAsyncTunnel.__init__À  s"   € ô ØØØØ!Ø)Øñ
ˆ�r   c                ó.   • U R                   R                  $ r#   )rì   rv   r@   s    r   rv   ÚAsyncTunnel.local_portÓ  s   € à�|‰|×&Ñ&Ð&r   c                ó.   • U R                   R                  $ r#   )rì   rŠ   r@   s    r   rŠ   ÚAsyncTunnel.remote_port×  s   € à�|‰|×'Ñ'Ð'r   c              ƒ  ó˜   #   • [         R                  " 5       nUR                  S U R                  R                  5      I S h  v•N   U $  N7fr#   )ÚasyncioÚget_running_loopÚrun_in_executorrì   r™   )r*   Úloops     r   Ú
__aenter__ÚAsyncTunnel.__aenter__Û  s=   é € Ü×'Ò'Ó)ˆØ×"Ñ" 4¨¯©×)<Ñ)<Ó=×=Ð=Øˆñ 	>ùs   ‚?A
ÁAÁA
c              ‡  ó–   #   • [         R                  " 5       nUR                  S U R                  R                  5      I S h  v•N   g  N7fr#   )ró   rô   rõ   rì   r>   )r*   r”   rö   s      r   Ú	__aexit__ÚAsyncTunnel.__aexit__à  s3   é € Ü×'Ò'Ó)ˆØ×"Ñ" 4¨¯©×);Ñ);Ó<×<Ó<ùs   ‚?A	ÁAÁA	c                ó8   • U R                   R                  5         g)z;Shut down the tunnel (sync, safe to call from any context).N)rì   r>   r@   s    r   r>   ÚAsyncTunnel.closeä  s   € à�‰×ÑÕr   )rì   rã   rä   )rB   rê   rå   rE   )rF   rG   rH   rI   rJ   r,   rè   rv   rŠ   r÷   rú   r>   rK   rL   r   r   rê   rê   ³  s’   † ñ
ð$ ØØ/3ñ
àð
ð ð
ð ð	
ð ð
ð ð
ð -ð
ð 
õ
ð& ó'ó ð'ð ó(ó ð(ôô
=÷r   rê   )r   r   r   rD   rB   rC   )r   r   rB   rD   )r   r   rT   rç   rB   rC   )'rJ   Ú
__future__r   ró   Úloggingrd   r   r'   rÃ   Úcollections.abcr   Útypingr   r   r   Úlangsmith.sandbox._helpersr   Úlangsmith.sandbox._ws_executer	   r³   r
   r   Ú	getLoggerrF   r¾   r   rÕ   rÖ   rØ   rÙ   r   r   r   r    rO   rj   rp   rr   rê   rL   r   r   Ú<module>r     s«   ðñõ #ã Û Û Û Û Û Ý #ß /Ñ /å 4Ý 9æßBà	×	Ò	˜8Ó	$€ð Ð à€	ØÐ ØÐ Ø!Ð àÐ ôKô
÷!ñ !ðP Ð ô1òr÷~ñ ~÷L3ò 3r   