fix(photon): use per-call httpx client in _sidecar_call

Prevents "Future attached to a different loop" errors when
_sidecar_call is invoked from a worker thread via _run_async in
send_message_tool. The persistent _http_client remains in use for
the inbound streaming loop, which always runs on the gateway's loop.
This commit is contained in:
underthestars-zhy 2026-06-11 13:28:43 -07:00 committed by Teknium
parent 9bfff6e16c
commit a23c0b378c

View file

@ -1177,14 +1177,18 @@ class PhotonAdapter(BasePlatformAdapter):
return SendResult(success=True, message_id=data.get("messageId"))
async def _sidecar_call(self, path: str, body: Dict[str, Any]) -> Dict[str, Any]:
# Guard: adapter not yet connected (no sidecar address known).
if self._http_client is None:
raise RuntimeError("Photon adapter not connected")
resp = await self._http_client.post(
f"http://{self._sidecar_bind}:{self._sidecar_port}{path}",
json=body,
headers={"X-Hermes-Sidecar-Token": self._sidecar_token},
timeout=30.0,
)
# Use a fresh client per call so this method is safe when invoked from
# a worker thread that owns a different event loop than the one the
# persistent _http_client was created on (e.g. via _run_async in
# send_message_tool). The inbound streaming loop continues to use
# _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:
resp = await client.post(url, json=body, headers=headers)
if resp.status_code != 200:
raise RuntimeError(
f"Photon sidecar {path} returned {resp.status_code}: {resp.text[:200]}"