Documentation
¶
Overview ¶
Package client is a thin Go client that speaks the relay canonical shape (sdk/v1). Callers build a *v1.Request once and get a *Response or a stream of canonical events — regardless of the target.
Use Relay for the primary relay-server path (key pooling, routing, limits). Use For(ref, apiKey) to call any catalogued upstream host directly by model ref ("gpt-4o", "openai/gpt-4o", "gpt-4o@openai-direct") with zero manual baseURL/path/auth wiring. OpenAI, Anthropic, and Gemini constructors remain for explicit off-catalog targets.
Configuration mirrors the OpenAI SDK: base URL, API key, auth header/scheme, extra default headers, request path, and HTTP client are all settable.
Imports only the standard library, pkg/relay/v1, and the pure vendor translators — none of relay's server-side dependency graph.
Index ¶
- Constants
- func KnownAdapterNames() []string
- type APIError
- type Adapter
- type Auth
- type Client
- func Anthropic(baseURL, apiKey string, opts ...Option) *Client
- func For(ref, apiKey string, opts ...TargetOption) (*Client, error)
- func Gemini(baseURL, apiKey string, opts ...Option) *Client
- func New(translator v1.Translator, baseURL, path, apiKey string, opts ...Option) *Client
- func OpenAI(baseURL, apiKey string, opts ...Option) *Client
- func OpenAIResponses(baseURL, apiKey string, opts ...Option) *Client
- func Relay(baseURL, relayKey string, opts ...Option) *Client
- func RelayWS(baseURL, relayKey string, opts ...Option) *Client
- type Event
- type Option
- type Response
- type Stream
- type StreamTiming
- type Target
- type TargetOption
Constants ¶
const ( EnvBaseURL = "WR_BASE_URL" EnvAPIKey = "WR_API_KEY" EnvUsage = "WR_USAGE" EnvHeaders = "WR_HEADERS" EnvTimeout = "WR_TIMEOUT" )
Relay env vars, mirroring the OpenAI SDK's OPENAI_BASE_URL / OPENAI_API_KEY convention. Only the relay target consults them — direct-to-vendor clients do not, so an upstream call never depends on relay config.
WR_BASE_URL relay endpoint (fallback when baseURL == "")
WR_API_KEY relay key (fallback when relayKey == "")
WR_USAGE default X-WR-Usage value (e.g. "full" to echo usage inline)
WR_HEADERS default headers, "k1=v1,k2=v2"
WR_TIMEOUT sync-call timeout, a Go duration (e.g. "30s"); streams are
unaffected — a stream needs no overall deadline.
const ( EnvOpenAIKey = "OPENAI_API_KEY" EnvAnthropicKey = "ANTHROPIC_API_KEY" // Gemini reads GEMINI_API_KEY first, then GOOGLE_API_KEY — matching the // google-genai SDK precedence. EnvGeminiKey = "GEMINI_API_KEY" EnvGoogleKey = "GOOGLE_API_KEY" )
Conventional per-vendor key env vars, read when a direct-to-vendor constructor is called with an empty apiKey. These are the vendor's own credential — never WR_API_KEY, which is a relay key bound to a relay endpoint and meaningless to a vendor. An empty key after fallback is left as-is (Ollama and other keyless OpenAI-compatible hosts are valid).
Variables ¶
This section is empty.
Functions ¶
func KnownAdapterNames ¶
func KnownAdapterNames() []string
KnownAdapterNames returns every adapter name registered in the SDK.
Types ¶
type APIError ¶
APIError is a non-2xx response from the target. Host names the upstream the call actually hit (a relay deployment or a vendor host dialed directly), so the error self-identifies its origin.
type Adapter ¶
type Adapter struct {
// contains filtered or unexported fields
}
Adapter is the atomic wire bundle: translator, path resolution, and auth always travel together. Selecting an adapter swaps all three at once.
func AdapterByName ¶
AdapterByName returns a registered adapter bundle, or false.
type Auth ¶
type Auth struct {
Header string // header name, e.g. "Authorization" or "x-api-key"
Scheme string // value prefix, e.g. "Bearer"; "" sends the raw key
}
Auth describes how the API key is attached to requests.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client sends canonical requests to one target (relay or a vendor).
func Anthropic ¶
Anthropic targets the Anthropic Messages API directly. Bypasses relay. Empty apiKey falls back to ANTHROPIC_API_KEY.
func For ¶
func For(ref, apiKey string, opts ...TargetOption) (*Client, error)
For resolves a model ref against the embedded catalog and returns a wired client. ref forms: "gpt-4o", "openai/gpt-4o", "gpt-4o@openai-direct".
func Gemini ¶
Gemini targets the Gemini native generateContent API directly. Bypasses relay. Point baseURL at the API host (e.g. https://generativelanguage.googleapis.com). Empty apiKey falls back to GEMINI_API_KEY, then GOOGLE_API_KEY. Auth is the raw key in x-goog-api-key.
func New ¶
func New(translator v1.Translator, baseURL, path, apiKey string, opts ...Option) *Client
New builds a client for an arbitrary translator/target — the extension point for future adapters. Defaults to Authorization: Bearer auth.
func OpenAI ¶
OpenAI targets the OpenAI Chat Completions API directly (also Ollama and any OpenAI-compatible host — point baseURL at it). Bypasses relay. Empty apiKey falls back to OPENAI_API_KEY.
func OpenAIResponses ¶
OpenAIResponses targets the OpenAI Responses API (`/responses`) directly, the same wire the Codex/ChatGPT subscription backend speaks. Point baseURL at the host (e.g. https://chatgpt.com/backend-api/codex). Bypasses relay. Empty apiKey falls back to OPENAI_API_KEY; for OAuth, pass a placeholder + WithAuth (Auth{}) and supply the bearer via WithHTTPClient. The Responses translator always sends store:false, so no server-side persistence is requested.
func Relay ¶
Relay targets a relay server's canonical endpoint (POST /v1/generate). The primary use: full key pooling, routing, limits, and observability.
Empty baseURL/relayKey fall back to WR_BASE_URL / WR_API_KEY; WR_USAGE, WR_HEADERS, and WR_TIMEOUT supply further defaults. Explicit opts override env-derived headers. Any missing/invalid config is returned on the client anyway and surfaces on the first Generate/GenerateStream call — never at construction.
func RelayWS ¶
RelayWS targets a relay server's canonical WebSocket endpoint (/v1/ws). One long-lived connection carries every request, so the TLS + auth handshake is paid once instead of per turn — the win for agent loops doing many sequential generations against the same relay.
The connection is stateless: each turn still sends the full request (relay holds no conversation state). This v1 client is sequential — one request in flight at a time per Client; concurrent multiplexing from a single Client is a future enhancement. Call Close when done.
func (*Client) Close ¶
Close releases the client's transport. For the default HTTP transport it is a no-op; for a WebSocket client (RelayWS) it closes the connection. Safe to call once when done with the client.
type Event ¶
Event is one canonical stream event: its name (a v1.Event* constant) and the raw JSON payload. Decode Data into the matching v1 event struct as needed.
type Option ¶
type Option func(*Client)
Option configures a Client. Options apply over the preset defaults.
func WithHTTPClient ¶
WithHTTPClient overrides the *http.Client. Streaming needs a client without a short overall timeout.
func WithHeader ¶
WithHeader sets one extra default header sent on every request (e.g. an OpenAI-Organization header, or anthropic-version override).
type Stream ¶
type Stream struct {
// contains filtered or unexported fields
}
Stream iterates canonical events. For a relay target the upstream stream is already canonical (toCanon is nil, frames pass through); for a vendor target toCanon converts each vendor SSE frame to canonical.
func (*Stream) Cost ¶
Cost returns total cost from the target's pricing rate sheet after the stream's terminal usage event has been received. ok is false for relay targets, unpriced hosts, and when usage is not yet available.
func (*Stream) Timing ¶
func (s *Stream) Timing() StreamTiming
Timing reports the stream timing observed so far. Call it after draining the stream for the full picture; mid-stream it reflects events up to the last Recv (ResponseEnd is zero until io.EOF).
type StreamTiming ¶
type StreamTiming struct {
Upstream usage.UpstreamTiming // Start == ResponseStart == TTFT; ResponseEnd == close
Reasoning *usage.ReasoningTiming // nil when the stream carried no reasoning
}
StreamTiming is the client-side timing of one streamed generation, in the exact shape relay ships server-side (usage.UpstreamTiming + usage.ReasoningTiming, microseconds from the GenerateStream call). A consumer reads identical fields whether it called relay or a provider directly — no drift, no branching on the path.
The client has no separate relay→upstream handoff, so Upstream.Start is collapsed onto ResponseStart (both = TTFT); when relay is in the path the relay server records its own earlier Start in its own event.
type Target ¶
type Target struct {
// contains filtered or unexported fields
}
Target is a fully-resolved, self-consistent upstream call config.
binding (and therefore the pricing behind Cost) reflects the catalog entry the ref resolved to. Overrides (WithBaseURL/WithAdapterName) change where and how the call is made but keep that pricing — fine for a same-price proxy, potentially stale if pointed at a genuinely different upstream.
type TargetOption ¶
TargetOption overrides one whole piece of a catalog-resolved Target before the client is built. Each option yields a consistent config — path and translator are only ever swapped via an Adapter.
func WithAdapterName ¶
func WithAdapterName(name string) TargetOption
WithAdapterName swaps the whole wire bundle (translator + path + auth).
func WithBaseURL ¶
func WithBaseURL(url string) TargetOption
WithBaseURL overrides the resolved host base URL (proxy/gateway). Adapter and auth are unchanged.
func WithClient ¶
func WithClient(opts ...Option) TargetOption
WithClient attaches client Options (custom *http.Client, extra headers, sync timeout, ...) to a catalog-resolved client. They apply over the adapter's defaults at construction.
func WithUpstreamModel ¶
func WithUpstreamModel(name string) TargetOption
WithUpstreamModel overrides the wire model name sent upstream.