Generic OpenAI-compatible streaming client with retry.
Purpose
-------
:class:`OpenAICompatClient` is a :class:`BaseClient` for any lane that
speaks the OpenAI chat-completions dialect. It is written FRESH on the
shape the DeepSeek bundle proved (plan 215 P2) — this module imports
nothing from ``providers.deepseek`` — and parameterises the two things
that differ per lane: the base URL and the extra request headers three
of the lanes need to pass their WAF or their attribution requirements.
Responsibilities
----------------
- :class:`OpenAICompatClient` — ``stream_chat`` / ``one_shot`` /
``list_models`` against one lane's endpoint.
- :func:`_is_retryable` — auth errors fail fast; transient HTTP and
network errors retry.
- :func:`_plain` — recursively coerce SDK/pydantic objects to plain
dicts so no model object leaks past this client.
Diagnostics
-----------
Domain: OC_CHAT.CLIENT
Levels:
L2 — lifecycle events
L3 — semantic details
L4 — deep tracing
Contracts
---------
- Up to 3 attempts on transient errors, delays 1/2/4 seconds.
- Authentication failures are NEVER retried — a wrong key does not
become right, and retrying burns a free lane's daily request budget.
- ``stream_chat`` yields ``("reasoning", str)``, ``("content", str)``,
``("tool_call", dict)``, ``("usage", dict)`` in arrival order, then a
terminal ``("finish_reason", str)`` — the CONTRACTS.md §5 tuple
contract, identical to the DeepSeek client's.
- The SDK is constructed with ``max_retries=0`` (we own the backoff) and
an httpx client with ``trust_env=False``, so the transport-trust env
family (HTTP(S)_PROXY / ALL_PROXY / SSL_CERT_* / REQUESTS_CA_BUNDLE)
cannot MITM or redirect the provider transcript (M8.0 WU-4c, F72/F79).
This mirrors the DeepSeek client deliberately: a new egress path that
silently re-trusted the environment would be a security regression.
- ``extra_headers`` carries lane metadata ONLY (User-Agent, attribution).
The API key travels via the SDK's own auth handling and is never
placed in a header dict here.
Dependencies
------------
- oc_diagnostics (structured debug logging via _dbg)
- openai (chat-completions client and streaming)
- httpx (lazy; transport with trust_env disabled)
- option_c_agent_contracts (lazy; SupportsCancellation type of the stream_chat cancellation token)