Ë
    ³Œj­:  ã                  ó*  — 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Zddl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mZ  ej,                  e«      Zd	ZdZd	Zd
ZdZdZdd„Zdd„Z  G d„ d«      Z!dZ"dd„Z#d„ Z$ G d„ d«      Z% G d„ d«      Z&y)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                ó`   — | j                  t        j                  t        t        |«      «       y)zAWrite the 3-byte connect header on a freshly opened yamux stream.N)ÚwriteÚstructÚpackÚ_CONNECT_HEADER_FMTÚPROTOCOL_VERSION)ÚstreamÚports     úc/var/www/html/Fitness-lenito-AI-main/venv/lib/python3.12/site-packages/langsmith/sandbox/_tunnel.pyÚ_write_connect_headerr   )   s   € à
‡L�L”—‘Ô0Ô2BÀDÓIÕJó    c                óH   — | j                  d«      }|st        d«      ‚|d   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                  ó0   — e Zd ZdZdd„Zdd„Zd	d„Zd
d„Zy)Ú
_WSAdaptera
  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   — || _         t        «       | _        t        j                  «       | _        y ©N)Ú_wsÚ	bytearrayÚ_bufÚ	threadingÚLockÚ_write_lock)ÚselfÚwss     r   Ú__init__z_WSAdapter.__init__C   s!   € ØˆŒÜ“KˆŒ	Ü$Ÿ>™>Ó+ˆÕr   c                ó`  — t        | j                  «      |k  rn| j                  j                  «       }t	        |t
        «      r|j                  «       }| j                  j                  |«       t        | j                  «      |k  rŒnt        | j                  d | «      }| j                  d |…= |S r"   )	Úlenr%   r#   ÚrecvÚ
isinstanceÚstrÚencodeÚextendÚbytes)r)   ÚnÚmsgÚresults       r   r   z_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                ó¤   — | j                   5  | j                  j                  |«       d d d «       t        |«      S # 1 sw Y   t        |«      S xY wr"   )r(   r#   Úsendr-   )r)   r   s     r   r   z_WSAdapter.writeS   s:   € Ø×ÓØ�H‰H�M‰M˜$Ô÷ ä�4‹yÐ÷ ä�4‹yÐús	   �<¼Ac                óX   — 	 | j                   j                  «        y # t        $ r Y y w xY wr"   )r#   ÚcloseÚ	Exception©r)   s    r   r:   z_WSAdapter.closeX   s'   € ð	Ø�H‰H�N‰NÕøÜò 	Ùð	ús   ‚ �	)¨)N)r*   r   ÚreturnÚNone)r4   Úintr=   r3   )r   r3   r=   r?   ©r=   r>   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r+   r   r   r:   © r   r   r    r    ;   s   „ ñó,ó
	óô
r   r    i @  c                ó4  ‡ ‡‡— t        j                  «       Šdˆˆ ˆfd„}dˆˆ ˆfd„}t        j                  |d¬«      }t        j                  |d¬«      }|j                  «        |j                  «        ‰j	                  «        	 ‰ j                  «        	 ‰j                  t        j                  «       	 ‰j                  «        |j                  d¬«       |j                  d¬«       y# t        $ r Y Œaw xY w# t        $ r Y ŒPw xY w# t        $ r Y ŒNw xY w)	z:Copy data bidirectionally until one side closes or errors.c                 óÈ   •— 	 	 ‰j                  t        «      } | sn‰j                  | «       Œ*	 ‰j	                  «        y # t        $ r Y Œw xY w# ‰j	                  «        w xY wr"   )r   Ú_BRIDGE_BUF_SIZEÚsendallr;   Úset©r   Údoner   Útcp_conns    €€€r   Ú_stream_to_tcpz_bridge.<locals>._stream_to_tcpj   sc   ø€ ð		ØØ—{‘{Ô#3Ó4�ÙØØ× Ñ  Ô&ð	 ð ð
 �H‰H�Jøô ò 	Ùð	ûð �H‰H�Júó(   ƒ+A  ®A Á 	AÁ	A ÁAÁA ÁA!c                 óÈ   •— 	 	 ‰j                  t        «      } | sn‰j                  | «       Œ*	 ‰j	                  «        y # t        $ r Y Œw xY w# ‰j	                  «        w xY wr"   )r.   rH   r   r;   rJ   rK   s    €€€r   Ú_tcp_to_streamz_bridge.<locals>._tcp_to_streamv   sa   ø€ ð		ØØ—}‘}Ô%5Ó6�ÙØØ—‘˜TÔ"ð	 ð ð
 �H‰H�Jøô ò 	Ùð	ûð �H‰H�JúrO   T)ÚtargetÚdaemoné   )ÚtimeoutNr@   )r&   ÚEventÚThreadÚstartÚwaitr:   r;   ÚshutdownÚsocketÚ	SHUT_RDWRÚOSErrorÚjoin)r   rM   rN   rQ   Út1Út2rL   s   ``    @r   Ú_bridgera   f   sè   ú€ ä�?‰?Ó€D÷
÷
ô 
×	Ñ	 ¸Ô	=€BÜ	×	Ñ	 ¸Ô	=€BØ‡H�H„JØ‡H�H„Jà‡I�I„KðØ�‰ŒðØ×Ñœ&×*Ñ*Ô+ðØ�‰Ôð ‡G�G�A€GÔØ‡G�G�A€GÕøô ò Ùðûô ò Ùðûô ò Ùðús6   ÂC- ÂC< Â8D Ã-	C9Ã8C9Ã<	DÄDÄ	DÄDc                 óF   — 	 ddl m}  | S # t        $ r t        d«      d‚w xY w)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.clientrc   ÚImportError)Ú
ws_connects    r   Ú_ensure_websocketsrg   Ÿ   s6   € ð	Ý@àÐøÜò Üð.ó
ð ð		ðús   ‚
 Š c                  ó¸   — e Zd ZdZdZdZddddœ	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Zedd	„«       Ze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d„Zy)ÚTunnela  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s || _        | j                  | _        || _        d | _        d | _        d | _	        d | _
        t        j                  «       | _        d| _        d| _        y )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_portrl   rm   rn   s          r   r+   zTunnel.__init__Ã   s€   € ð ,ˆÔØˆŒØˆŒØ'ˆÔØ%/Ò%>°;ˆÔ"Ø×5Ñ5ˆÔØ-ˆÔàˆŒØ.2ˆŒØ7;ˆÔØ:>ˆÔÜ(Ÿ~™~Ó/ˆÔØˆŒØˆ�r   c                ó   — | j                   S )z&Local port the tunnel is listening on.)ru   r<   s    r   rl   zTunnel.local_portÝ   s   € ð ×ÑÐr   c                ó   — | j                   S )z4Port inside the sandbox that the tunnel connects to.)rs   r<   s    r   r€   zTunnel.remote_portâ   s   € ð × Ñ Ð r   c                ó   — | S r"   rE   r<   s    r   Ú	__enter__zTunnel.__enter__é   s   € Øˆr   c                ó$   — | j                  «        y r"   )r:   )r)   Úargss     r   Ú__exit__zTunnel.__exit__ì   s   € Ø�
‰
�r   c                óŠ   — | j                   ry d| _         	 | j                  «        y # t        $ r | j                  «        ‚ w xY w)NT)r|   Ú	_do_startr;   r:   r<   s    r   Ú_startzTunnel._startñ   s=   € Ø�=Š=ØØˆŒð	Ø�N‰NÕøÜò 	Ø�J‰JŒLØð	ús	   –' §Ac                ó‚  — | j                  «        t        j                  t        j                  t        j                  «      | _        | j                  j                  t        j                  t        j                  d«       | j                  }|dk7  rvt        j                  t        j                  t        j                  «      }	 |j                  d«       |j                  d|f«       |j                  «        t        d|› d�«      ‚| j                  j!                  d| j                  f«       | j                  j#                  d	«       | j                  j%                  «       d   | _        t)        j*                  | j,                  d
d¬«      | _        | j.                  j1                  «        y # t        $ r Y n@t        $ r5}dt        |«      v rndt        |«      j                  «       v r‚ 	 Y d }~nd }~ww xY w	 |j                  «        �Œ# t        $ r Y �Œw xY w# 	 |j                  «        w # t        $ r Y w w xY wxY w)Nr   r   rj   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)rR   rS   Úname)Ú_connectr[   ÚAF_INETÚSOCK_STREAMrx   Ú
setsockoptÚ
SOL_SOCKETÚSO_REUSEADDRrt   Ú
settimeoutrc   r:   r]   ÚConnectionRefusedErrorr0   ÚlowerÚbindÚlistenÚgetsocknameru   r&   rW   Ú_accept_loopry   rX   )r)   r   ÚprobeÚes       r   r‰   z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øÜò Ùðýsm   ÃAF. Æ.	G6Æ7H Æ9G6Ç+G1Ç,H Ç1G6Ç6H Ç:H È	HÈHÈH>ÈH/È.H>È/	H;È8H>È:H;È;H>c                óp  — ddl m} | j                  }|r	 |j                  «        t        «       }| j                  «       }t        | j                  rd| j                  ind| j                  «      } |||t        dd¬«      | _        t        | j                  «      } ||«      | _        y# t        $ r Y ŒŽw xY w)z:Establish (or re-establish) the WebSocket + yamux session.r   )r
   z	X-Api-KeyNrT   )Úadditional_headersÚopen_timeoutÚclose_timeoutÚping_interval)Úlangsmith.sandbox._yamuxr
   rw   r:   r;   rg   Ú_build_ws_urlr   rq   rr   r	   r#   r    )r)   r
   Ú	old_yamuxrf   Úws_urlrn   Úadapters          r   rŽ   zTunnel._connect(  sª   € å9à—K‘Kˆ	ÙðØ—‘Ô!ô (Ó)ˆ
Ø×#Ñ#Ó%ˆÜØ,0¯MªMˆ[˜$Ÿ-™-Ñ(¸tØ�M‰Mó
ˆñ
 ØØ&Ü(ØØô
ˆŒô ˜TŸX™XÓ&ˆÙ" 7Ó+ˆ�øô' ò Ùðús   –B) Â)	B5Â4B5c                óº  — ddl m} | j                  r"| j                  j                  s| j                  S | j                  5  | j                  r+| j                  j                  s| j                  cddd«       S d}t        | j                  «      D ]B  }	 | j                  «        t        j                  d|dz   «       | j                  c cddd«       S   |d| j                  › d�«      |‚# t        $ rY}|}|| j                  dz
  k  r;t        | j                  d|z  z  | j                  «      }t        j                  |«       Y d}~Œ¹d}~ww xY w# 1 sw Y   yxY w)	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¨   rw   Ú	is_closedrz   Úrangerv   rŽ   ÚloggerÚdebugr;   ÚminÚ_BACKOFF_BASEÚ_BACKOFF_MAXÚtimeÚsleep)r)   r¨   Úlast_errÚattemptÚexcÚdelays         r   Ú_ensure_sessionz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   Á.EÁ9EÂ4C,ÃEÃEÃ,	EÃ5AE	ÅEÅ	EÅEÅEc                óæ   — | j                   ryd| _         | j                  r	 | j                  j                  «        | j                  r| j                  j                  «        yy# t        $ r Y Œ3w xY w)z.Shut down the tunnel, closing all connections.NT)r{   rx   r:   r]   rw   r<   s    r   r:   zTunnel.closec  se   € à�<Š<ØØˆŒà×ÒðØ×#Ñ#×)Ñ)Ô+ð �;Š;Ø�K‰K×ÑÕð øô ò Ùðús   ¢A$ Á$	A0Á/A0c                óö   — | j                   s^	 | j                  j                  «       \  }}t	        j
                  | j                  |fdd¬«      j                  «        | j                   sŒ]y y # t        $ r Y y w xY w)NTztunnel-bridge)rR   r†   rS   r�   )r{   rx   Úacceptr]   r&   rW   Ú_handle_connrX   )r)   ÚconnÚ_s      r   rš   zTunnel._accept_loopt  sp   € Ø—,’,ðØ×-Ñ-×4Ñ4Ó6‘��aô ×ÑØ×(Ñ(Ø�WØØ$ô	÷
 ‰eŒgð —,•,øô ò Ùðús   ŽA, Á,	A8Á7A8c                ó´  — 	 | j                  «       }|j                  «       }t        || j                  «       t	        |«      }|t
        k(  rt        ||«       y |j                  «        |j                  «        |t        k(  r!t        j                  d| j                  «       y |t        k(  r!t        j                  d| j                  «       y |t        k(  rt        j                  dt        «       y t        j                  d|«       y # t        $ rF}t        j                  d|«       	 |j                  «        n# t         $ r Y nw xY wY d }~y Y d }~y d }~ww xY w)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   rs   r   Ú	STATUS_OKra   r:   ÚSTATUS_PORT_NOT_ALLOWEDr¬   ÚwarningÚSTATUS_DIAL_FAILEDÚSTATUS_UNSUPPORTED_VERSIONr   r;   r­   r]   )r)   rM   Úsessionr   Ústatusrµ   s         r   r»   zTunnel._handle_conn�  s  € ð$	Ø×*Ñ*Ó,ˆGØ×(Ñ(Ó*ˆFÜ! &¨$×*;Ñ*;Ô<Ü! &Ó)ˆFàœÒ"Ü˜ Ô)Øà�L‰LŒNØ�N‰NÔàÔ0Ò0Ü—‘Ø;Ø×%Ñ%õð Ô-Ò-Ü—‘ØIØ×%Ñ%õð Ô5Ò5Ü—‘ØDÜ$õô
 —‘Ð:¸FÕCøäò 	Ü�L‰LÐ?ÀÔEðØ—‘Õ øÜò ÙðúÜô !ûð	úsU   ‚AD ÁA	D Â#)D Ã#D Ã1D Ä	EÄEÄ(D9Ä8EÄ9	EÅEÅEÅEÅEc                ó†   — | j                   j                  d«      }|j                  dd«      j                  dd«      }|› d�S )NÚ/zhttps://zwss://zhttp://zws://z/tunnel)rp   ÚrstripÚreplace)r)   Úurls     r   r£   zTunnel._build_ws_url¨  sA   € Ø×!Ñ!×(Ñ(¨Ó-ˆØ�k‰k˜* hÓ/×7Ñ7¸	À7ÓKˆØ��gˆÐr   ©r~   r0   r   zOptional[str]r€   r?   rl   r?   rm   r?   rn   zOptional[Mapping[str, str]]r=   r>   ©r=   r?   )r=   ri   ©r†   Úobjectr=   r>   r@   )r=   r
   )rM   úsocket.socketr=   r>   )r=   r0   )rA   rB   rC   rD   r¯   r°   r+   Úpropertyrl   r€   r„   r‡   rŠ   r‰   rŽ   r·   r:   rš   r»   r£   rE   r   r   ri   ri   ­   sÃ   „ ñð$ €MØ€Lð ØØ/3ñàðð ðð ð	ð ðð ðð -ðð 
óð4 ò ó ð ð ò!ó ð!óóó
	ó*$óX,ó:ó< ó"ó%ôNr   ri   c                  óx   — e Zd ZdZddddœ	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Zedd„«       Zedd„«       Zdd	„Zdd
„Z	dd„Z
y)ÚAsyncTunnelaw  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   Nrk   c               ó0   — t        ||||||¬«      | _        y )Nrk   )ri   Ú_tunnelr}   s          r   r+   zAsyncTunnel.__init__À  s"   € ô ØØØØ!Ø)Øô
ˆ�r   c                ó.   — | j                   j                  S r"   )rÕ   rl   r<   s    r   rl   zAsyncTunnel.local_portÓ  s   € à�|‰|×&Ñ&Ð&r   c                ó.   — | j                   j                  S r"   )rÕ   r€   r<   s    r   r€   zAsyncTunnel.remote_port×  s   € à�|‰|×'Ñ'Ð'r   c              ƒ  ó–   K  — t        j                  «       }|j                  d | j                  j                  «      ƒ d {  –—†  | S 7 Œ­wr"   )ÚasyncioÚget_running_loopÚrun_in_executorrÕ   rŠ   )r)   Úloops     r   Ú
__aenter__zAsyncTunnel.__aenter__Û  s>   è ø€ Ü×'Ñ'Ó)ˆØ×"Ñ" 4¨¯©×)<Ñ)<Ó=×=Ð=Øˆð 	>ús   ‚>A	Á AÁA	c              ‡  ó”   K  — t        j                  «       }|j                  d | j                  j                  «      ƒ d {  –—†  y 7 Œ­wr"   )rÙ   rÚ   rÛ   rÕ   r:   )r)   r†   rÜ   s      r   Ú	__aexit__zAsyncTunnel.__aexit__à  s4   è ø€ Ü×'Ñ'Ó)ˆØ×"Ñ" 4¨¯©×);Ñ);Ó<×<Ò<ús   ‚>AÁ AÁAc                ó8   — | j                   j                  «        y)z;Shut down the tunnel (sync, safe to call from any context).N)rÕ   r:   r<   s    r   r:   zAsyncTunnel.closeä  s   € à�‰×ÑÕr   rÌ   rÍ   )r=   rÓ   rÎ   r@   )rA   rB   rC   rD   r+   rÑ   rl   r€   rÝ   rß   r:   rE   r   r   rÓ   rÓ   ³  s’   „ ñ
ð$ ØØ/3ñ
àð
ð ð
ð ð	
ð ð
ð ð
ð -ð
ð 
ó
ð& ò'ó ð'ð ò(ó ð(óó
=ôr   rÓ   )r   r   r   r?   r=   r>   )r   r   r=   r?   )r   r   rM   rÐ   r=   r>   )'rD   Ú
__future__r   rÙ   Úloggingr[   r   r&   r±   Úcollections.abcr   Útypingr   r   r   Úlangsmith.sandbox._helpersr   Úlangsmith.sandbox._ws_executer	   r¢   r
   r   Ú	getLoggerrA   r¬   r   rÀ   rÁ   rÃ   rÄ   r   r   r   r    rH   ra   rg   ri   rÓ   rE   r   r   Ú<module>rè      s­   ðñõ #ã Û Û Û Û Û Ý #ß /Ñ /å 4Ý 9áßBà	ˆ×	Ñ	˜8Ó	$€ð Ð à€	ØÐ ØÐ Ø!Ð àÐ óKó
÷!ñ !ðP Ð ó1òr÷~ñ ~÷L3ò 3r   