* fix(llm): set HTTP timeout on Gemini clients (#785)
* fix(embedding): set HTTP timeout on Gemini embedding client (#785)
Same wedge-class failure as the LLM client: a stalled Gemini embedding
socket hangs the in-process reconciler, which shares the deriver worker's
uvloop event loop. Apply the same 10-minute timeout here, in lockstep
with src/llm/registry.py's _build_gemini_http_options.
* style(test): drop extra blank line in test_registry imports
* feat: send OpenRouter app-attribution headers on OpenAI-compatible clients
Sets HTTP-Referer and X-Title on every AsyncOpenAI client constructed in
src/llm/registry.py (default, override-cached, and module-level CLIENTS) and
in the embedding client, so OpenRouter attributes Honcho's requests to the
"Honcho" app in its dashboard/analytics. Other OpenAI-compatible providers
ignore unrecognized headers, so this is safe to send unconditionally.
* fix: scope OpenRouter attribution headers to OpenRouter base URL only
Address review feedback on #805:
- Only inject attribution headers when the configured base_url starts
with https://openrouter.ai (via new _openrouter_headers() helper)
- Rename X-Title to X-Openrouter-Title per OpenRouter docs recommendation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor: drive default headers from base-URL map, drop embedding path
Replace the OpenRouter-specific _openrouter_headers helper with a generic
_DEFAULT_HEADERS_BY_BASE_URL prefix map + _default_headers_for lookup, so
OpenRouter always receives its attribution headers and another provider can be
added with a single map entry. Revert the embedding-client change (OpenRouter
has no embeddings endpoint, so that gate was dead code) and add a unit test for
the lookup helper.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>