Files
hermes-agent/hermes_cli/proxy
briandevans 8f6df4a82a fix(proxy): resolve the 401/429 retry credential off the event loop
`handle_proxy` already offloads the two credential reads on the happy path,
but the rotation inside the `upstream_resp.status in {401, 429}` branch still
called `adapter.get_retry_credential` inline on the event loop.

That is the most expensive of the three blocking methods on the
`UpstreamAdapter` contract, not the cheapest:

  * `NousPortalAdapter.get_retry_credential` routes into
    `_get_credential(force_refresh=True)`, so the token-refresh POST that
    `get_credential` performs only near expiry is unconditional here — and it
    runs under the same `_auth_store_lock()`, a cross-process advisory lock
    with a 15s timeout.
  * `XAIGrokAdapter.get_retry_credential` loads the key pool off disk and
    calls `try_refresh_current` / `mark_exhausted_and_rotate` under its lock.

So every upstream 401 or 429 froze the proxy's single event loop — and with
it every other in-flight streaming completion — for the whole rotation. A 429
is exactly when the proxy is busiest, which is the worst moment to stall.

Wrap it in `asyncio.to_thread`, matching the two sites above. The error
contract is unchanged: `to_thread` re-raises the worker's exception in the
awaiting frame, so the existing `except Exception -> retry_cred = None` still
swallows a failed rotation and streams the upstream's own rejection back.
2026-09-03 01:56:32 +05:30
..
…