§
    ÷žyjI  ã                  óÖ   — d Z ddlmZ ddlZddlZddlZddlmZm	Z	 ddl
mZmZ dadd„Z G d	„ d
¦  «        Z G d„ d¦  «        Zd d„Zd!d„Z	 d"dddœd#d„Zd$d„Z e¦   «         Zg d¢ZdS )%u·  Process-level bootstrap helpers for ``run_agent``.

Three concerns, all tied to ``AIAgent`` boot-time / runtime IO setup:

1. **Lazy OpenAI SDK import** â€” ``_load_openai_cls`` + ``_OpenAIProxy``
   defer the 240ms-ish ``from openai import OpenAI`` cost until first use,
   while preserving ``isinstance(client, OpenAI)`` checks and
   ``patch("run_agent.OpenAI", ...)`` test patterns.

2. **Crash-resistant stdio** â€” ``_SafeWriter`` wraps stdout/stderr so
   ``OSError: Input/output error`` from broken pipes (systemd, Docker,
   thread teardown races) cannot crash the agent.  ``_install_safe_stdio``
   applies the wrapper.

3. **HTTP proxy resolution** â€” ``_get_proxy_from_env`` reads
   ``HTTPS_PROXY`` / ``HTTP_PROXY`` / ``ALL_PROXY``;
   ``_get_proxy_for_base_url`` respects ``NO_PROXY`` for the given base URL.

``run_agent`` re-exports every name so existing
``from run_agent import _get_proxy_from_env`` imports keep working
unchanged.
é    )ÚannotationsN)ÚAnyÚOptional)Úbase_url_hostnameÚnormalize_proxy_urlÚreturnÚtypec                 ó.   — t           €ddlm}  | a t           S )z#Import and cache ``openai.OpenAI``.Nr   )ÚOpenAI)Ú_OPENAI_CLS_CACHEÚopenair   )Ú_clss    ú=/home/ragecks/.hermes/hermes-agent/agent/process_bootstrap.pyÚ_load_openai_clsr   '   s(   € õ Ð Ø)Ð)Ð)Ð)Ð)Ð)Ø ÐÝÐó    c                  ó(   — e Zd ZdZdZd„ Zd„ Zd„ ZdS )Ú_OpenAIProxyzHModule-level proxy that looks like ``openai.OpenAI`` but imports lazily.© c                ó*   —  t          ¦   «         |i |¤ŽS ©N)r   )ÚselfÚargsÚkwargss      r   Ú__call__z_OpenAIProxy.__call__5   s   € Ø!ÕÑ!Ô! 4Ð2¨6Ð2Ð2Ð2r   c                ó:   — t          |t          ¦   «         ¦  «        S r   )Ú
isinstancer   )r   Úobjs     r   Ú__instancecheck__z_OpenAIProxy.__instancecheck__8   s   € Ý˜#Õ/Ñ1Ô1Ñ2Ô2Ð2r   c                ó   — dS )Nz<lazy openai.OpenAI proxy>r   ©r   s    r   Ú__repr__z_OpenAIProxy.__repr__;   s   € Ø+Ð+r   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__r   r   r!   r   r   r   r   r   0   sL   € € € € € ØRÐRà€Ið3ð 3ð 3ð3ð 3ð 3ð,ð ,ð ,ð ,ð ,r   r   c                  ó:   — e Zd ZdZdZd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
d	S )
Ú_SafeWriterup  Transparent stdio wrapper that catches OSError/ValueError from broken pipes.

    When hermes-agent runs as a systemd service, Docker container, or headless
    daemon, the stdout/stderr pipe can become unavailable (idle timeout, buffer
    exhaustion, socket reset). Any print() call then raises
    ``OSError: [Errno 5] Input/output error``, which can crash agent setup or
    run_conversation() â€” especially via double-fault when an except handler
    also tries to print.

    Additionally, when subagents run in ThreadPoolExecutor threads, the shared
    stdout handle can close between thread teardown and cleanup, raising
    ``ValueError: I/O operation on closed file`` instead of OSError.

    This wrapper delegates all writes to the underlying stream and silently
    catches both OSError and ValueError. It is transparent when the wrapped
    stream is healthy.
    )Ú_innerc                ó>   — t                                | d|¦  «         d S )Nr)   )ÚobjectÚ__setattr__)r   Úinners     r   Ú__init__z_SafeWriter.__init__T   s    € Ý×Ò˜4 ¨5Ñ1Ô1Ð1Ð1Ð1r   c                ó²   — 	 | j                              |¦  «        S # t          t          f$ r) t	          |t
          ¦  «        rt          |¦  «        ndcY S w xY w)Nr   )r)   ÚwriteÚOSErrorÚ
ValueErrorr   ÚstrÚlen)r   Údatas     r   r0   z_SafeWriter.writeW   sb   € ð	=Ø”;×$Ò$ TÑ*Ô*Ð*øÝ�Ð$ð 	=ð 	=ð 	=Ý *¨4µÑ 5Ô 5Ð<•3�t‘9”9�9¸1Ð<Ð<Ð<ð	=øøøs   ‚ œ7AÁAc                ój   — 	 | j                              ¦   «          d S # t          t          f$ r Y d S w xY wr   )r)   Úflushr1   r2   r    s    r   r7   z_SafeWriter.flush]   sH   € ð	ØŒK×ÒÑÔÐÐÐøÝ�Ð$ð 	ð 	ð 	ØˆDˆDð	øøøs   ‚ �2±2c                ó4   — | j                              ¦   «         S r   )r)   Úfilenor    s    r   r9   z_SafeWriter.filenoc   s   € ØŒ{×!Ò!Ñ#Ô#Ð#r   c                óf   — 	 | j                              ¦   «         S # t          t          f$ r Y dS w xY w)NF)r)   Úisattyr1   r2   r    s    r   r;   z_SafeWriter.isattyf   sB   € ð	Ø”;×%Ò%Ñ'Ô'Ð'øÝ�Ð$ð 	ð 	ð 	Ø�5�5ð	øøøs   ‚ ›0¯0c                ó,   — t          | j        |¦  «        S r   )Úgetattrr)   )r   Únames     r   Ú__getattr__z_SafeWriter.__getattr__l   s   € Ý�t”{ DÑ)Ô)Ð)r   N)r"   r#   r$   r%   r&   r.   r0   r7   r9   r;   r?   r   r   r   r(   r(   ?   s   € € € € € ðð ð$ €Ið2ð 2ð 2ð=ð =ð =ðð ð ð$ð $ð $ðð ð ð*ð *ð *ð *ð *r   r(   úOptional[str]c                 óš   — dD ]G} t           j                             | d¦  «                             ¦   «         }|rt	          |¦  «        c S ŒHdS )zÑRead proxy URL from environment variables.

    Checks HTTPS_PROXY, HTTP_PROXY, ALL_PROXY (and lowercase variants) in order.
    Returns the first valid proxy URL found, or None if no proxy is configured.
    )ÚHTTPS_PROXYÚ
HTTP_PROXYÚ	ALL_PROXYÚhttps_proxyÚ
http_proxyÚ	all_proxyÚ N)ÚosÚenvironÚgetÚstripr   )ÚkeyÚvalues     r   Ú_get_proxy_from_envrO   p   sZ   € ð:ð .ð .ˆå”
—’˜s BÑ'Ô'×-Ò-Ñ/Ô/ˆØð 	.Ý& uÑ-Ô-Ð-Ð-Ð-ð	.àˆ4r   Úbase_urlc                óº   — t          ¦   «         }|r| s|S t          | ¦  «        }|s|S 	 t          j                             |¦  «        rdS n# t
          $ r Y nw xY w|S )zFReturn an env-configured proxy unless NO_PROXY excludes this base URL.N)rO   r   ÚurllibÚrequestÚproxy_bypass_environmentÚ	Exception)rP   ÚproxyÚhosts      r   Ú_get_proxy_for_base_urlrX   ~   s‰   € åÑ!Ô!€EØð ˜ð Øˆå˜XÑ&Ô&€DØð ØˆðÝŒ>×2Ò2°4Ñ8Ô8ð 	Ø�4ð	øåð ð ð Øˆðøøøð €Ls   ©A Á
AÁArH   FT)Ú
async_modeÚverifyr3   rY   ÚboolrZ   r   úOptional[Any]c               óL  — 	 ddl }t          | ¦  «        }|                     ddd¬¦  «        }|                     dddd¬	¦  «        }|r|j        n|j        }|r|j        n|j        }i }	|€ ||¬
¦  «         ||¬
¦  «        dœ}	 |||||	pd|¬¦  «        S # t          $ r Y dS w xY w)aƒ  Build an httpx client for OpenAI SDK calls with env-only proxy policy.

    Uses explicit ``HTTPS_PROXY`` / ``NO_PROXY`` env vars via
    ``_get_proxy_for_base_url``. Plain no-proxy mounts disable httpx's default
    ``trust_env`` proxy path, so macOS system proxy settings from
    ``urllib.request.getproxies()`` (which omit the ExceptionsList) are not
    applied. Mirrors ``AIAgent._build_keepalive_http_client``.

    Connection lifecycle is managed at the HTTP pool layer
    (``keepalive_expiry=20.0`` reaps idle connections before reverse proxies'
    typical 30-60 s timeouts) instead of the former custom
    ``socket_options`` transport, which broke streaming behind reverse
    proxies (#54049, #12952) and stalled TLS handshakes by stripping
    ``TCP_NODELAY``.

    ``verify`` is forwarded to httpx so auxiliary-client calls (compression,
    vision, web_extract, title generation, etc.) honor the same per-provider
    ``ssl_ca_cert`` / ``ssl_verify`` and ``HERMES_CA_BUNDLE`` settings the main
    client uses. It is passed on the client AND on the plain no-proxy mounts
    (a mounted transport owns the SSL context for its scheme).
    r   Né   éd   g      4@)Úmax_keepalive_connectionsÚmax_connectionsÚkeepalive_expiryg      .@g      $@)ÚconnectÚreadr0   Úpool)rZ   )zhttp://zhttps://)ÚlimitsÚtimeoutrV   ÚmountsrZ   )	ÚhttpxrX   ÚLimitsÚTimeoutÚAsyncHTTPTransportÚHTTPTransportÚAsyncClientÚClientrU   )
rP   rY   rZ   ri   rV   rf   rg   Útransport_clsÚ
client_clsrh   s
             r   Úbuild_keepalive_http_clientrr   ‘   s
  € ð6Øˆˆˆå'¨Ñ1Ô1ˆà—’Ø&(ØØ!ð ñ 
ô 
ˆð —-’-¨°4¸tÈ$�-ÑOÔOˆà4>ÐW˜Ô0Ð0ÀEÔDWˆØ*4ÐF�UÔ&Ð&¸%¼,ˆ
ØˆØˆ=à(˜=°Ð7Ñ7Ô7Ø)˜M°Ð8Ñ8Ô8ðð ˆFð ˆzØØØØ�>˜TØð
ñ 
ô 
ð 	
øõ ð ð ð Øˆtˆtðøøøs   ‚BB Â
B#Â"B#ÚNonec                 ó°   — dD ]R} t          t          | d¦  «        }|�8t          |t          ¦  «        s#t	          t          | t          |¦  «        ¦  «         ŒSdS )zHWrap stdout/stderr so best-effort console output cannot crash the agent.)ÚstdoutÚstderrN)r=   Úsysr   r(   Úsetattr)Ústream_nameÚstreams     r   Ú_install_safe_stdior{   Ì   s\   € à+ð ;ð ;ˆÝ�˜k¨4Ñ0Ô0ˆØÐ¥j°½Ñ&EÔ&EÐÝ•C˜¥k°&Ñ&9Ô&9Ñ:Ô:Ð:øð;ð ;r   )r   r   r   r(   r{   rO   rX   rr   )r   r	   )r   r@   )rP   r@   r   r@   )rH   )rP   r3   rY   r[   rZ   r   r   r\   )r   rs   )r%   Ú
__future__r   rI   rw   Úurllib.requestrR   Útypingr   r   Úutilsr   r   r   r   r   r(   rO   rX   rr   r{   r   Ú__all__r   r   r   ú<module>r�      sm  ððð ð. #Ð "Ð "Ð "Ð "Ð "à 	€	€	€	Ø 
€
€
€
Ø Ð Ð Ð Ø  Ð  Ð  Ð  Ð  Ð  Ð  Ð  à 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8ð
 Ð ðð ð ð ð,ð ,ð ,ð ,ð ,ñ ,ô ,ð ,ð.*ð .*ð .*ð .*ð .*ñ .*ô .*ð .*ðbð ð ð ðð ð ð ð( ð8ð Øð	8ð 8ð 8ð 8ð 8ð 8ðv;ð ;ð ;ð ;ð 
ˆ‰Œ€ð	ð 	ð 	€€€r   