Ë
    áß²j  ã                  ó¼   — d Z ddlmZ ddlZddlZddlZddlmZ dZdd„Z	dd„Z
ddd„Zd	Zdd
„Zdd„Zdd„Zdd„Zej"                  fdd„Zddd„Zddœ	 	 	 	 	 dd„Zy)az  NO_PROXY matching shared by the LLM transport (``agent/process_bootstrap.py``) and the
gateway platform adapters (``gateway/platforms/base.py``).

One matcher so "is this host in NO_PROXY" has one answer everywhere: exact hosts, domain
suffixes (``example.com``, ``.example.com``, ``*.example.com``), IP literals, CIDR ranges,
optional ``host:port`` entries and ``*``. The stdlib ``proxy_bypass_environment`` understands
none of the CIDR / ``*.`` forms, which is why the LLM path used to route ``10.x`` endpoints
through the corporate proxy while Telegram/Discord bypassed it.

Leaf module: stdlib only, importable during early boot.
é    )ÚannotationsN)Úurlsplit)ÚHTTPS_PROXYÚ
HTTP_PROXYÚ	ALL_PROXYÚhttps_proxyÚ
http_proxyÚ	all_proxyc                 ó6   ‡ — t        ˆ fd„t        D «       d«      S )zMFirst non-empty HTTPS_PROXY / HTTP_PROXY / ALL_PROXY value (any case), or ''.c              3  óŠ   •K  — | ]:  }t         j                  j                  |«      xs d j                  «       xŠsŒ7‰–— Œ< y­w©Ú N)ÚosÚenvironÚgetÚstrip)Ú.0ÚkÚvs     €ú7/home/ubuntu/.hermes/hermes-agent/agent/proxy_bypass.pyú	<genexpr>z(first_proxy_env_value.<locals>.<genexpr>   s6   øè ø€ ÒW�q´R·Z±Z·^±^ÀAÓ5FÒ5LÈ"×4SÑ4SÓ4UÐ/U¨qÑ/U”ÑWùs
   ƒ8A¼Ar   )ÚnextÚPROXY_ENV_KEYS©r   s   @r   Úfirst_proxy_env_valuer      s   ø€ äÓWœNÔWÐY[Ó\Ð\ó    c                óº  — t        | xs d«      j                  «       }|syd|v s|j                  d«      r)t        |«      }|j                  xs d}	 |j
                  }nÌ|j                  d«      rQd|v rM|dd j                  d«      \  }}}|j                  d	«      r!|dd j                  «       rt        |dd «      nd}nj|j                  d	«      dk(  rC|j                  d	«      d
   j                  «       r!|j                  d	«      \  }}}t        |«      }n|j                  d«      d}}|j                  «       j                  d«      |fS # t        $ r d}Y Œ.w xY w)zä``(host, port)`` from a URL (scheme optional: ``//host/path``), ``[v6]:port``,
    ``host:port`` or bare host; host lowercased. A malformed URL port (``host:abc``,
    ``host:99999``) yields ``(host, None)`` rather than raising.r   r   z://z//Nú[ú]é   ú:é   ú[]ú.)Ústrr   Ú
startswithr   ÚhostnameÚportÚ
ValueErrorÚ	partitionÚisdigitÚintÚcountÚ
rpartitionÚlowerÚrstrip)ÚvalueÚrawÚparsedÚhostr(   Ú_ÚrestÚport_ss           r   Úsplit_host_portr8      s?  € ô ˆeŠk�rÓ
×
 Ñ
 Ó
"€CÙØØ��|�s—~‘~ dÔ+Ü˜#“ˆØ�‰Ò$ "ˆð	Ø—;‘;‰Dð 
�‰˜Ô	 ¨¡Ø˜A˜B˜×)Ñ)¨#Ó.‰ˆˆa�Ø $§¡°Ô 4¸¸a¸b¸×9IÑ9IÔ9KŒs�4˜˜�8Œ}ÐQU‰Ø	�‰�3‹˜1Ò	 §¡°Ó!4°QÑ!7×!?Ñ!?Ô!AØŸ.™.¨Ó-‰ˆˆa�Ü�6‹{‰à—Y‘Y˜t“_ dˆdˆØ�:‰:‹<×Ñ˜sÓ# TÐ)Ð)øô ò 	ØŠDð	ús   ÁE ÅEÅEc                óª   — | €dj                  d„ dD «       «      } t        j                  d| j                  «       «      D �cg c]  }|sŒ|‘Œ	 c}S c c}w )zuComma/whitespace-separated NO_PROXY entries; from the environment (both casings) when
    ``no_proxy_value`` is None.ú,c              3  ó\   K  — | ]$  }t         j                  j                  |d «      –— Œ& y­wr   )r   r   r   )r   Úkeys     r   r   z#no_proxy_entries.<locals>.<genexpr>9   s   è ø€ Ò!^¸c¤"§*¡*§.¡.°°b×"9Ñ!^ùs   ‚*,©ÚNO_PROXYÚno_proxyz[\s,]+)ÚjoinÚreÚsplitr   )Úno_proxy_valueÚparts     r   Úno_proxy_entriesrE   5   sI   € ð ÐØŸ™Ñ!^ÐE]Ô!^Ó^ˆÜŸX™X i°×1EÑ1EÓ1GÓHÖQ�TÊDŠDÒQÐQùÒQs   ÁAÁ	A)z	127.0.0.1Ú	localhostz::1c                ó¾   — t        | xs d«      j                  «       j                  «       j                  d«      } t        | «      }| dk(  xs |duxr |j                  S )z�True for a host that must always bypass a proxy: ``localhost`` or any loopback IP literal
    (``127.x.x.x``, ``::1``, ``::ffff:127.0.0.1``).r   r#   rF   N)r%   r   r/   Ú_ip_or_noneÚis_loopback)r4   Úips     r   Úis_loopback_hostrK   G   sU   € ô ˆtŠz�r‹?× Ñ Ó"×(Ñ(Ó*×0Ñ0°Ó6€DÜ	�TÓ	€BØ�;ÑÒE 2¨T >Ò#D°b·n±nÐEr   c                ó<   — t        t        | «      d   «      rddiS i S )zã``websockets.connect`` kwargs for an in-process dial: ``{"proxy": None}`` when ``url``
    targets loopback (skip the library's system-proxy auto-detection), else ``{}`` so remote
    endpoints keep the default proxy behaviour.r   ÚproxyN©rK   r8   ©Úurls    r   Úloopback_connect_kwargsrQ   O   s$   € ô /¬¸sÓ/CÀAÑ/FÔGˆG�Tˆ?ÐOÈRÐOr   c                óB   — t        t        | «      d   «      rddddœiS i S )a	  ``requests.get`` kwargs for an in-process HTTP dial (CDP ``/json/version`` discovery /
    readiness): ``{"proxies": {"http": None, "https": None}}`` when ``url`` targets loopback so
    ``requests`` skips ``getproxies()`` (env and macOS system proxy), else ``{}``.r   ÚproxiesN)ÚhttpÚhttpsrN   rO   s    r   Úloopback_request_kwargsrV   V   s.   € ô :JÌ/ÐZ]ÓJ^Ð_`ÑJaÔ9bˆI ¨tÑ4Ð5ÐjÐhjÐjr   c                óì   ‡ — t        ˆ fd„dD «       «      r‰ S dD ]R  }t        ‰ j                  |«      xs d«      }t        D �cg c]	  }||vsŒ|‘Œ }}|sŒ<dj	                  ||z   «      ‰ |<   ŒT ‰ S c c}w )a  Append the loopback hosts to ``NO_PROXY`` / ``no_proxy`` in ``env`` (both casings),
    keeping every operator-provided entry; returns ``env``. An operator ``*`` (bypass everything)
    already covers loopback and would stop being the wildcard once anything is appended to it.c              3  ó^   •K  — | ]$  }d t        ‰j                  |«      xs d«      v –— Œ& y­w)Ú*r   N)rE   r   )r   r<   Úenvs     €r   r   z(add_loopback_no_proxy.<locals>.<genexpr>a   s)   øè ø€ Ò
[¸3ˆ3Ô" 3§7¡7¨3£<Ò#5°2Ó6Ô6Ñ
[ùs   ƒ*-r=   r   r:   )ÚanyrE   r   ÚLOOPBACK_HOSTSr@   )rZ   r<   Úentriesr4   Úmissings   `    r   Úadd_loopback_no_proxyr_   ]   s€   ø€ ô Ó
[ÐBZÔ
[Ô[Øˆ
Ø'ò 3ˆÜ" 3§7¡7¨3£<Ò#5°2Ó6ˆÜ$2ÖJ˜D°dÀ'Ò6I’4ÐJˆÐJÚØ—x‘x ¨'Ñ 1Ó2ˆC�ŠHð	3ð
 €Jùò Ks   Á	A1ÁA1c                ó2   — 	  || «      S # t         $ r Y yw xY w)zR``parse(value)`` or None on ``ValueError`` (``parse`` is ip_address / ip_network).N)r)   )r1   Úparses     r   rH   rH   k   s#   € ðÙ�U‹|ÐøÜò Ùðús   ‚
 Š	•c                ó\  — t        | xs d«      j                  «       j                  «       }|sy|dk(  ryt        |«      \  }}|r	|�|�||k7  ryt	        |«      }t	        |d„ «      }|�
|d uxr ||v S |j                  d«      j                  d«      }||k(  xs |j                  d|› �«      S )Nr   FrY   Tc                ó0   — t        j                  | d¬«      S )NF)Ústrict)Ú	ipaddressÚ
ip_networkr   s    r   ú<lambda>z(no_proxy_entry_matches.<locals>.<lambda>}   s   € ´	×0DÑ0DÀQÈuÔ0U€ r   r$   )r%   r   r/   r8   rH   ÚremoveprefixÚendswith)	Úentryr4   r(   ÚtokenÚ
token_hostÚ
token_portÚhost_ipÚnetworkÚsuffixs	            r   Úno_proxy_entry_matchesrq   s   sÅ   € Ü�’˜Ó×"Ñ"Ó$×*Ñ*Ó,€EÙØØ�‚|ØÜ,¨UÓ3Ñ€J�
Ù˜*Ð0°d°lÀjÐTXÒFXØÜ˜$Ó€GÜ˜*Ñ&UÓV€GØÐØ˜dÐ"Ò9 w°'Ð'9Ð9ð ×$Ñ$ SÓ)×6Ñ6°sÓ;€FØ�6‰>Ò8˜TŸ]™]¨Q¨v¨h¨<Ó8Ð8r   )rC   c          
     óÀ   ‡— t        |«      Š‰r| syt        | t        «      r| gn
t        | «      }t	        ˆfd„t        t        t        t        |«      «      D «       «      S )z…True when NO_PROXY (the environment, or ``no_proxy_value``) matches at least one target
    host (a URL, ``host:port`` or bare host).Fc              3  óZ   •‡‡K  — | ]   \  ŠŠ‰xr t        ˆˆfd „‰D «       «      –— Œ" y­w)c              3  ó8   •K  — | ]  }t        |‰‰«      –— Œ y ­w©N)rq   )r   rj   r4   r(   s     €€r   r   z0should_bypass_proxy.<locals>.<genexpr>.<genexpr>�   s   øè ø€ ÒTÀ5Ô+¨E°4¸×>ÑTùs   ƒN)r[   )r   r4   r(   r]   s    @@€r   r   z&should_bypass_proxy.<locals>.<genexpr>�   s2   úè ø€ ò FáˆD�$ð 	ÒT”ÔTÈGÔTÓTÓTñFùs   …&+)rE   Ú
isinstancer%   Úlistr[   Úmapr8   )Útarget_hostsrC   Ú
candidatesr]   s      @r   Úshould_bypass_proxyr{   †   sZ   ø€ ô
 ˜~Ó.€GÙ™,ØÜ#-¨l¼CÔ#@�,‘ÄdÈ<ÓFX€JÜó Fäœo¬s´3¸
Ó/CÓDôFó Fð Fr   )Úreturnr%   )r1   r%   r|   ztuple[str, int | None]ru   )rC   ú
str | Noner|   z	list[str])r4   r}   r|   Úbool)rP   r%   r|   Údict)rZ   r   r|   r   )r1   r%   )rj   r%   r4   r%   r(   z
int | Noner|   r~   )ry   z3str | list[str] | tuple[str, ...] | set[str] | NonerC   r}   r|   r~   )Ú__doc__Ú
__future__r   re   r   rA   Úurllib.parser   r   r   r8   rE   r\   rK   rQ   rV   r_   Ú
ip_addressrH   rq   r{   © r   r   ú<module>r…      sŒ   ðñ
õ #ã Û 	Û 	Ý !àe€ó]ó
*ô2Rð 3€óFóPókóð #,×"6Ñ"6ô ô9ð( hlñFØEðFØZdðFà	ôFr   