
    `gjI                        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y)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_urlc                 *    t         ddlm}  | a t         S )z#Import and cache ``openai.OpenAI``.r   )OpenAI)_OPENAI_CLS_CACHEopenair	   )_clss    J/root/.hermes/venv/lib/python3.12/site-packages/agent/process_bootstrap.py_load_openai_clsr   '   s      )     c                  &    e Zd ZdZdZd Zd Zd Zy)_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2622r   c                *    t        |t                     S r   )
isinstancer   )r   objs     r   __instancecheck__z_OpenAIProxy.__instancecheck__8   s    #/122r   c                     y)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   s    RI33,r   r   c                  8    e Zd ZdZdZd Zd Zd Zd Zd Z	d Z
y	)
_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                2    t         j                  | d|       y )Nr'   )object__setattr__)r   inners     r   __init__z_SafeWriter.__init__T   s    451r   c                    	 | j                   j                  |      S # t        t        f$ r" t	        |t
              rt        |      cY S dcY S w xY w)Nr   )r'   writeOSError
ValueErrorr   strlen)r   datas     r   r.   z_SafeWriter.writeW   sH    	=;;$$T**$ 	= *4 53t9<1<	=s    *A	AAc                d    	 | j                   j                          y # t        t        f$ r Y y w xY wr   )r'   flushr/   r0   r   s    r   r5   z_SafeWriter.flush]   s.    	KK$ 		s    //c                6    | j                   j                         S r   )r'   filenor   s    r   r7   z_SafeWriter.filenoc   s    {{!!##r   c                b    	 | j                   j                         S # t        t        f$ r Y yw xY w)NF)r'   isattyr/   r0   r   s    r   r9   z_SafeWriter.isattyf   s1    	;;%%''$ 		s    ..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,   r.   r5   r7   r9   r=   r   r   r   r&   r&   ?   s,    $ I2=$*r   r&   c                     dD ]?  } t         j                  j                  | d      j                         }|s4t	        |      c S  y)zRead 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_envrL   p   sC    : .

sB'--/&u--	.
 r   c                    t               }|r| s|S t        |       }|s|S 	 t        j                  j	                  |      ry	 |S # t
        $ r Y |S w xY w)zFReturn an env-configured proxy unless NO_PROXY excludes this base URL.N)rL   r   urllibrequestproxy_bypass_environment	Exception)base_urlproxyhosts      r   _get_proxy_for_base_urlrU   ~   se    !EX&D>>2248 9
 L  Ls   A 	AAFT)
async_modeverifyc               J   	 ddl }t        |       }|j                  ddd      }|j                  dddd	      }|r|j                  n|j
                  }|r|j                  n|j                  }i }	| ||
       ||
      d}	 |||||	xs d|      S # t        $ r Y y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readr.   pool)rW   )zhttp://zhttps://)limitstimeoutrS   mountsrW   )	httpxrU   LimitsTimeoutAsyncHTTPTransportHTTPTransportAsyncClientClientrQ   )
rR   rV   rW   rd   rS   ra   rb   transport_cls
client_clsrc   s
             r   build_keepalive_http_clientrm      s    6'1&(!  
 --4t$-O4>00EDWDW*4U&&%,,
=(7)8F >T
 	
  s   BB 	B"!B"c                     dD ]A  } t        t        | d      }|t        |t              r(t	        t        | t        |             C y)zHWrap stdout/stderr so best-effort console output cannot crash the agent.)stdoutstderrN)r;   sysr   r&   setattr)stream_namestreams     r   _install_safe_stdioru      s?    + ;k40j&ECk&&9:;r   )r	   r   r   r&   ru   rL   rU   rm   )returntype)rv   Optional[str])rR   rx   rv   rx   )rE   )rR   r1   rV   boolrW   r   rv   zOptional[Any])rv   None)r#   
__future__r   rF   rq   urllib.requestrN   typingr   r   utilsr   r   r
   r   r   r&   rL   rU   rm   ru   r	   __all__r   r   r   <module>r      s   . # 	 
    8
  , ,.* .*b( 8 	88 8 	8
 8v; 
	r   