- llm.py: _create() wrapper retries APIConnectionError (incl. timeout) up to
LLM_MAX_ATTEMPTS=3 with LLM_RETRY_DELAY_SECONDS=5s backoff; 4xx still fails
fast. The local LLM server is shared with Hermes and serializes requests, so
a request can be dropped by the client timeout while queued — chat/send was
500ing on that.
- helpers.py: internal_error() now logs full exception detail server-side
(was only the type name), so 500s are diagnosable; client message unchanged.
- config.py: LLM_MAX_ATTEMPTS / LLM_RETRY_DELAY_SECONDS env knobs.
- tests: test_llm_retry_queue (transient retried, 4xx not retried, no retry on
success), test_internal_error_logging (detail in log, hidden from client,
order-independent via explicit handler + logger re-enable).