oc_chat
Loading...
Searching...
No Matches
providers.openai_compat.client Namespace Reference

Classes

class  OpenAICompatClient

Functions

bool _is_retryable (Exception exc)
Any _plain (Any value)

Variables

tuple _RETRY_DELAYS = (1, 2, 4)
dict _RETRYABLE_STATUS = {429, 500, 502, 503, 524}

Detailed Description

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)

Function Documentation

◆ _is_retryable()

bool providers.openai_compat.client._is_retryable ( Exception exc)
protected
Return True if *exc* is a transient error worth retrying.

Definition at line 78 of file client.py.

Here is the caller graph for this function:

◆ _plain()

Any providers.openai_compat.client._plain ( Any value)
protected
Recursively convert pydantic / arbitrary objects to plain dicts and lists.

Definition at line 87 of file client.py.

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ _RETRY_DELAYS

tuple providers.openai_compat.client._RETRY_DELAYS = (1, 2, 4)
protected

Definition at line 74 of file client.py.

◆ _RETRYABLE_STATUS

dict providers.openai_compat.client._RETRYABLE_STATUS = {429, 500, 502, 503, 524}
protected

Definition at line 75 of file client.py.