From 6294703dec259756fa4a3214c4ed3e7e1189e775 Mon Sep 17 00:00:00 2001 From: DI404N Date: Wed, 17 Jun 2026 23:51:40 +0800 Subject: [PATCH] fix: disable httpx proxy for Photon sidecar localhost connections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All Photon sidecar HTTP requests target 127.0.0.1 — they should never be routed through a system HTTP proxy. When trust_env=True (the default), httpx picks up macOS system proxy settings and routes localhost requests through the proxy. If the proxy returns a spurious response (e.g. 502), _reap_stale_sidecar() interprets it as 'port in use by a non-sidecar process' and refuses to start, yielding: 'pids: unknown, not a Photon sidecar'. Set trust_env=False on all five httpx.AsyncClient call sites in the Photon adapter so localhost sidecar communication bypasses the system proxy entirely. --- plugins/platforms/photon/adapter.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/platforms/photon/adapter.py b/plugins/platforms/photon/adapter.py index 535eb9898a1f..ed3e966d58da 100644 --- a/plugins/platforms/photon/adapter.py +++ b/plugins/platforms/photon/adapter.py @@ -485,7 +485,7 @@ class PhotonAdapter(BasePlatformAdapter): ) return False - client = httpx.AsyncClient(timeout=30.0) + client = httpx.AsyncClient(timeout=30.0, trust_env=False) self._http_client = client # The sidecar holds the gRPC stream for BOTH directions, so it is @@ -981,7 +981,7 @@ class PhotonAdapter(BasePlatformAdapter): if sys.platform == "win32": # lsof/ps; orphaning is a POSIX-only path return try: - async with httpx.AsyncClient(timeout=2.0) as client: + async with httpx.AsyncClient(timeout=2.0, trust_env=False) as client: await client.post( f"http://{self._sidecar_bind}:{self._sidecar_port}/healthz", headers={"X-Hermes-Sidecar-Token": self._sidecar_token}, @@ -1107,7 +1107,7 @@ class PhotonAdapter(BasePlatformAdapter): # Wait for /healthz to come up — give it up to 15s on cold start. deadline = time.time() + 15.0 last_err: Optional[Exception] = None - async with httpx.AsyncClient(timeout=2.0) as client: + async with httpx.AsyncClient(timeout=2.0, trust_env=False) as client: while time.time() < deadline: if self._sidecar_proc.poll() is not None: raise RuntimeError( @@ -1670,7 +1670,7 @@ class PhotonAdapter(BasePlatformAdapter): # _http_client directly — it always runs on the gateway's loop. url = f"http://{self._sidecar_bind}:{self._sidecar_port}{path}" headers = {"X-Hermes-Sidecar-Token": self._sidecar_token} - async with httpx.AsyncClient(timeout=30.0) as client: + async with httpx.AsyncClient(timeout=30.0, trust_env=False) as client: resp = await client.post(url, json=body, headers=headers) if resp.status_code != 200: raise RuntimeError( @@ -1810,7 +1810,7 @@ async def _standalone_send( headers = {"X-Hermes-Sidecar-Token": token} last_message_id: Optional[str] = None try: - async with httpx.AsyncClient(timeout=30.0) as client: + async with httpx.AsyncClient(timeout=30.0, trust_env=False) as client: # 1. Text body first (if any), so it leads the conversation. if message: send_body: Dict[str, Any] = {