core

package module
v0.12.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 25, 2026 License: MIT Imports: 15 Imported by: 0

README

llmgw-core

Headless, embeddable LLM routing engine and resilient multi-provider proxy for Go.

Highlights

  • Headless & Zero Database: Pure Go http.Handler. Mounts anywhere (net/http, Chi, Gin, Fiber, Echo) without requiring SQLite, PostgreSQL, or any storage engine.
  • Bi-Directional Wire Translation: Full Anthropic Messages API (/v1/messages) support translated dynamically to OpenAI backends (and SSE streaming) via llm-translate.
  • Resilient Multi-Provider Routing: Route aliases, ordered failover chains, rate-limit 429 detection, and circuit breaking.
  • Pluggable Extension Hooks:
    • Authenticator: Custom token, session, or API key validation.
    • PolicyGate: RBAC, project-level, or model-level permission gates.
    • CredentialResolver: Dynamic or multi-tenant credential overrides (BYOC).
    • UsageHook: Telemetry, cost tracking, and audit logging.
  • Shared Provider Contracts: Typed connection/auth kinds, catalog and completion evidence, health classification, exact target publication policy, and a persistence-agnostic ProviderConnector interface.

Installation

go get github.com/xibodev/llmgw-core
Dependencies
  • llm-provider-auth v0.6.0. Its codex package no longer supplies a client version, so providers.NewCodex and NewCodexProvider require ClientVersion, the version of the product making the call, and return an error when it is blank. The providers send it to the Codex catalog as client_version. ResponsesURL and ModelsURL still default to the canonical Codex endpoints.
  • llm-translate v0.3.0. Conversions report the vendor fields inside messages that the target surface cannot carry, and the translation adapter enforces those losses; see Loss policy. The Anthropic and Codex providers have no loss report, so they keep serving the histories they served before. The Anthropic provider carries the cache_control of Chat text parts into the Messages request, system prompt included.

Quick Start (Embedded in 15 Lines)

package main

import (
    "net/http"
    "github.com/xibodev/llmgw-core"
    "github.com/xibodev/llmgw-core/providers"
)

func main() {
    engine := core.NewEngine(core.Config{
        Routes: map[string]core.RouteConfig{
            "smart": {
                Targets: []core.Target{
                    {Provider: "groq", Model: "llama-3.3-70b-versatile"},
                    {Provider: "openai", Model: "gpt-4o"},
                },
            },
        },
    })

    // Register backends
    engine.RegisterProvider("openai", providers.NewOpenAIProvider("openai", "https://api.openai.com/v1", os.Getenv("OPENAI_API_KEY"), nil))
    engine.RegisterProvider("groq", providers.NewOpenAIProvider("groq", "https://api.groq.com/openai/v1", os.Getenv("GROQ_API_KEY"), nil))

    // Mount on standard HTTP server
    http.Handle("/v1/", engine)
    http.ListenAndServe(":8080", nil)
}

Provider registry

providers.DefaultRegistry() is the reviewed, validated manifest of curated provider integrations. Core owns each entry's wire and safety facts: runtime, protocol, auth methods, connection scope, risk classification, and anonymous automation. A product layers its own curation on top with an overlay, and the result is validated like a manifest:

overlay, err := providers.DecodeOverlay(overlayJSON) // strict: unknown fields fail
registry, err := providers.DefaultRegistry().WithOverlay(overlay, providers.ValidationOptions{
    RuntimeTypes: []string{"openai_compatible", "anthropic"}, // what this product can execute
})
entry, ok := registry.Lookup("gpt") // ids and aliases, case-insensitive

An overlay can:

  • Override presentation, priority, and curation fields of existing entries: label, description, categories, icon, domain, docs URL, priority, availability, common models, onboarding fields, additional aliases, and product-private extensions.
  • Add product-only entries under their own ids.
  • Remove entries the product does not offer.

An override cannot change wire or safety facts. A product that needs different wire behavior adds its own entry instead. Entries() orders by priority, then by manifest order, so an overlay without priorities keeps the manifest order.

Anonymous providers use one mechanism:

  • Registry.AnonymousProfiles lists the entries curated for anonymous automation.
  • AdmitAnonymousModel applies each provider's reviewed free-model rules to a raw catalog row. It fails closed: unknown providers are never admitted, and OpenCode Zen is admitted only from its verified metadata.
  • SelectVerificationModel picks the model to probe.
  • DiscoverAnonymousModels combines them.

Whether to enroll an anonymous provider remains the product's policy.

Provider contract

The wire-level contract shared by products and transports:

  • Caller identifies who a request acts for. LocalCaller() is the caller of a single-user application.
  • Provider serves a Request{Surface, Model, Body, ContentType, Credential} for the surfaces it lists in NativeSurfaces.
    • It returns a Response{Body, ContentType, Losses}, or a StreamIter of complete SSE frames.
    • Bodies are bytes: JSON for the chat surfaces, multipart form data for speech-to-text, and binary for speech, images and video.
    • A request for any other surface fails with a *SurfaceError, and a translation adapter serves it instead.
  • Errors classify themselves. ClassifyError(err).Disposition() says whether to retry, fail over, or stop. ProviderError carries a message that is safe to show and a cause that is never rendered.
  • LossPolicy decides which translation and adaptation losses a product accepts, by field-path glob, class and severity. Allowed losses are still reported, in Response.Losses and through a stream's LossReporter.

Products supply three stores, each with an in-memory reference implementation:

  • CredentialStore is the llm-provider-auth token store plus Resolve(ctx, caller, instance), which returns the key of the credential that serves a caller. Which credential applies is product policy. The Runtime keeps it fresh through tokenstore.Coordinator. APIKeyRecord stores a static key that never refreshes. Reference: NewMemoryCredentialStore.
    • A provider receives CredentialFromRecord(key, record): the access token as APIKey or Token, plus the record's AccountID, TokenType and a copy of its Metadata, such as a project ID.
    • A Credential prints and logs whether each secret is set, never its value. Metadata may hold secrets, so it is never serialized.
  • CatalogStore keeps discovered catalogs, with a new revision on every save. Save must be atomic for readers in any process. Run catalogtest.Run against every implementation. Reference: NewMemoryCatalogStore.
  • EvidenceSink receives AccountEvidence: which credential served which operation, and the classified outcome. Reference: MemoryEvidenceSink.

Runtime

runtime.Runtime is the one value that owns a product's provider state: the registry, the provider cache, the refresh coordinators, the catalog cache and health. The core packages keep no package state and read no environment, and an architecture test enforces both.

rt, err := runtime.New(runtime.Options[Settings]{
    Settings:    settingsSource, // Snapshot() (Settings, generation)
    Providers:   buildProvider,  // func(Settings, instance) (core.Provider, error)
    Credentials: credentialStore,
    Refresh:     oauthRefresh,   // per instance; nil means credentials never refresh
    Catalogs:    catalogStore,
    Evidence:    evidenceSink,
    Registry:    registry,
})
response, err := rt.Invoke(ctx, caller, "openai", request)

The Runtime works with the product's own settings type:

  • It rebuilds providers and coordinators when the settings generation changes.
  • It resolves each caller's credential and refreshes an OAuth credential the upstream rejects with 401, once, before replaying. Static API keys are never replayed.
  • It serves stored catalogs while they are fresh, sharing them across processes through the CatalogStore.
  • Only upstream outcomes (an HTTP status or a transport failure) change an instance's health.

translation.Adapter{Provider, Policy} serves surfaces a provider lacks by translating through llm-translate:

  • Messages over Chat Completions, streaming included.
  • Chat Completions over Responses.
  • Responses over Chat Completions.
Loss policy

Request losses are checked against the LossPolicy before the provider is called, and the response losses of Invoke once it answers. A stream's response losses are reported but not enforced, because its frames are already delivered. All losses, including the provider's own and those the policy allows, are returned in Response.Losses or through the stream's LossReporter.

Gemini returns a thought signature with each tool call and needs it back on the next turn. No other surface can carry one, so llm-translate reports each dropped signature as a material loss at its path, such as messages.1.tool_calls.0.extra_content.google.thought_signature. The default policy rejects unmatched material losses, so the adapter refuses:

  • a Chat request whose history carries signatures, served over Responses;
  • a Chat response that carries them, converted for a Messages or Responses client, after the provider has answered.

The refusal is a *LossPolicyError, which permits failover to a target that serves the surface natively. Under the same policy, a Messages stream over Chat Completions still serves signed tool calls and only reports the loss.

A product that serves Gemini through the adapter should consider allowing the loss, which is still reported:

policy := core.LossPolicy{Rules: []core.LossRule{
    {Path: "**.thought_signature", Class: translate.LossDropped, Action: core.LossAllow},
}}

Allowing it loses nothing on a request to a model other than Gemini: that model cannot use the signature, and the caller's history keeps it. A client that receives a translated Gemini response, though, never sees the signature, so its next turn reaches Gemini without it.

Dropped reasoning_details, reasoning_content and cache_control, and dropped reasoning items or thinking blocks, reported at <path>.reasoning, are advisory: the default policy allows and reports them, and a product that depends on them rejects them by path.

Codex

providers.Codex is a whole provider vertical on the provider contract: the Codex Responses transport, the catalog and what its rows mean, and, with NewCodexRefresh, the credential refresh. None of it is left for a product to normalize.

rt, err := runtime.New(runtime.Options[Settings]{
    Settings: settingsSource,
    Providers: func(s Settings, instance string) (core.Provider, error) {
        codex, err := providers.NewCodex(providers.CodexConfig{
            Instructions:  s.CodexInstructions,
            ClientVersion: s.CodexClientVersion, // names the product; required
        })
        if err != nil {
            return nil, err
        }
        return translation.Adapter{Provider: codex}, nil // Messages over Chat
    },
    Refresh: func(s Settings, instance string) tokenstore.RefreshFunc {
        return providers.NewCodexRefresh(codexauth.Config{ClientID: s.CodexClientID})
    },
    Credentials: credentialStore,
})
  • Credential. Each request authenticates with its own credential: the token is the bearer and AccountID becomes the ChatGPT-Account-ID header. A credential without a token, such as an API key, is a configuration error, and nothing is sent.
  • Surfaces. Responses and Chat Completions are native, and both stream. A shorthand string input is sent as the one user message it abbreviates. Chat is converted to Responses with the gateway's Chat field policy: fields Codex cannot carry, such as max_tokens and temperature, are dropped and reported as advisory losses, and a field that would change the answer's structure is refused. CodexConfig.ResponsesOnly leaves Chat to a translation.Adapter and the product's loss policy instead.
  • Catalog. ListModels returns only rows supported in the API and listed. A row that omits supported_endpoints, as current catalogs do, gets /responses. The parser was verified against the catalog of providers.CodexVerifiedClientVersion; it is not a default, and ClientVersion must still be set.
  • Refresh. A rejected token fails with status 401, so the Runtime refreshes once and replays. Each credential refreshes with the OAuth client its metadata names (core.CredentialMetadataOAuthClientID, falling back to the configured client), and a browser login as that public PKCE client. The refreshed record keeps the account, taken from the token response or its ID token, so a refresh that returns another account is refused. A grant the token endpoint rejects for good revokes the credential.
  • Errors are *core.ProviderError, with the transport's error as the cause.

CodexProvider, which reads tokens from a session source, is deprecated. It shares the transport, so both send identical requests.

Execution

execution holds the primitives failover is built from. Endpoints, policy gates, translation-loss routing and affinity stay product code: a product orders its candidates and hands the list over.

  • HealthTracker keeps each key's circuit and cooldown behind a mutex, with an injectable clock. Consecutive circuit failures open the circuit at FailureThreshold, for OpenDuration or what a Backoff returns. After that it is half-open: the next failure reopens it and a success closes it. A Retry-After keeps the key unavailable until then. Policies can differ per key. Observe, the default reading of an error, uses core.ClassifyError, and a product can replace it.
  • Execute tries candidates in order. It skips unavailable ones, stops at a terminal disposition, and moves on after a failover or retryable one, repeating the candidate first only when Retry asks. It records outcomes and returns the result with a trace of every candidate reached. A canceled context stops it and records nothing.
  • ExecuteStream commits to a candidate once a frame carries output, content or reasoning, as the product's predicate decides. Earlier frames are held back, so a failure before output moves to the next candidate unseen. After output nothing fails over: a failure reaches the caller as the stream's *AfterOutputError.
tracker := execution.NewHealthTracker(execution.HealthOptions{})
executor := execution.Executor[core.Target]{
    Health: tracker,
    Key:    func(target core.Target) string { return target.Provider },
}
result, err := execution.ExecuteStream(ctx, executor, targets, open, carriesOutput)
if err != nil {
    return err // result.Attempts still holds the trace
}
defer result.Value.Close()

OAuth flows

oauthflow.Service runs the server-side sign-in flows both products expose: browser authorization codes with PKCE, device authorization, and codes the user pastes back. Products keep their HTTP routes and map each onto one call:

svc, err := oauthflow.New(oauthflow.Options{
    // Or a shared store. The memory store can cap each caller's pending flows.
    Store:         oauthflow.NewMemoryFlowStore(oauthflow.MemoryFlowStoreOptions{MaxFlowsPerCaller: 5}),
    Credentials:   credentialStore, // core.CredentialStore
    Drivers:       driverFor,       // (instance, method) -> Driver
    CredentialKey: keyFor,          // product policy
})
view, err := svc.Start(ctx, caller, "antigravity", oauthflow.MethodBrowser,
    oauthflow.WithRedirectURI(callbackURL))
view, err = svc.Callback(ctx, oauthflow.CompleteInput{Code: code, State: state})
  • A FlowStore binds each flow to the whole Caller that started it. Another caller gets ErrFlowNotFound, as if the flow did not exist.
  • Consume is atomic and single-use, and an expired flow is never consumed. Run oauthflowtest.Run against every implementation.
  • Poll never asks the provider more often than the flow's interval, even across processes, and honours slow_down.
  • Complete and Callback consume the flow before the code exchange, so a code is used at most once even when the exchange fails. A pasted redirect URL whose state does not match spends nothing, so the user can paste again.
  • Verifiers, OAuth states, device codes and tokens stay on the server. The returned View never holds them.
  • Credentials are saved through CredentialStore.Save under a key the product chooses.
  • BrowserPKCE is a ready driver over llm-provider-auth's browseroauth.

The package documentation maps each gateway and Facet Studio route onto the Service.

License

MIT

Documentation

Index

Constants

View Source
const (
	// CredentialMetadataOAuthProfile names how the owner signed in, such as
	// a device or a browser login. The provider defines the values.
	CredentialMetadataOAuthProfile = "oauth_profile"
	// CredentialMetadataOAuthClientID is the OAuth client the grant belongs to.
	CredentialMetadataOAuthClientID = "oauth_client_id"
	// CredentialMetadataOAuthClientMode is how that client authenticates,
	// such as public or confidential.
	CredentialMetadataOAuthClientMode = "oauth_client_mode"
	// CredentialMetadataOAuthRedirectURI is the redirect URI of a browser
	// login.
	CredentialMetadataOAuthRedirectURI = "oauth_redirect_uri"
	// CredentialMetadataOAuthClientSecret is a confidential client's secret.
	CredentialMetadataOAuthClientSecret = "oauth_client_secret"
	// CredentialMetadataAccountLabel is a label for the account, such as an
	// email address, for display.
	CredentialMetadataAccountLabel = "account_label"
)

Metadata keys under which a record carries what its OAuth grant needs later, the way the gateway's credential store keeps them. A refresh reads them so each credential refreshes with the client it was granted to, not whichever client is configured now.

View Source
const (
	EvidenceOperationInvoke     = "invoke"
	EvidenceOperationStream     = "stream"
	EvidenceOperationListModels = "list_models"
)

Operations named in AccountEvidence.

View Source
const (
	ContentTypeJSON        = "application/json"
	ContentTypeEventStream = "text/event-stream"
)

Content types of JSON bodies and SSE streams.

View Source
const ModelCapabilitiesSchemaVersion = 1
View Source
const TokenTypeAPIKey = "api_key"

TokenTypeAPIKey marks a token-store record that holds a static API key rather than an OAuth access token.

Variables

View Source
var ErrCatalogNotFound = errors.New("core: catalog not found")

ErrCatalogNotFound reports that no catalog is stored for a key.

View Source
var ErrNoCredential = errors.New("core: no credential resolves for this caller and instance")

ErrNoCredential reports that no credential resolves for a caller and a provider instance.

Functions

func APIKeyRecord added in v0.9.0

func APIKeyRecord(apiKey string) tokenstore.Record

APIKeyRecord returns the token-store record of a static API key. It has no expiry, so tokenstore.Coordinator never refreshes it.

func KnownModelSurface added in v0.9.0

func KnownModelSurface(surface ModelSurface) bool

KnownModelSurface reports whether a surface is defined by this version.

func NewProviderOperationError added in v0.3.0

func NewProviderOperationError(op string, statusCode int, retryAfter string, err error) error

NewProviderOperationError creates a classifiable provider error. Callers should not put response bodies, credentials, or private endpoints in op.

func ServesNatively added in v0.9.0

func ServesNatively(provider Provider, model string, surface ModelSurface) bool

ServesNatively reports whether provider serves surface for model without translation.

Types

type AccountEvidence added in v0.9.0

type AccountEvidence struct {
	Caller   Caller
	Instance string
	// CredentialKey and CredentialRevision identify the token-store record
	// that served the operation; AccountID is the account it is bound to.
	CredentialKey      string
	CredentialRevision string
	AccountID          string
	Operation          string
	Surface            ModelSurface
	Model              string
	// Outcome is the classified result, including when it was observed.
	Outcome ProviderHealthEvidence
}

AccountEvidence attributes one provider operation to the credential that served it, so a product can audit usage and detect a stale or replaced credential. It carries no secrets.

type AllowAllPolicy

type AllowAllPolicy struct{}

AllowAllPolicy is a PolicyGate that permits all requests.

func (AllowAllPolicy) Allows

func (AllowAllPolicy) Allows(ctx context.Context, principal *Principal, target Target) (bool, string)

type Authenticator

type Authenticator interface {
	Authenticate(r *http.Request) (*Principal, error)
}

Authenticator authenticates an incoming HTTP request. If not configured, requests proceed as anonymous.

type AuthenticatorFunc

type AuthenticatorFunc func(r *http.Request) (*Principal, error)

AuthenticatorFunc is a functional adapter for Authenticator.

func (AuthenticatorFunc) Authenticate

func (f AuthenticatorFunc) Authenticate(r *http.Request) (*Principal, error)

type Caller added in v0.9.0

type Caller struct {
	ID        string     `json:"id"`
	Kind      CallerKind `json:"kind"`
	ProjectID string     `json:"project_id,omitempty"`
}

Caller identifies who a request acts for. Products map their own identity types onto it; core never needs more than these fields. ProjectID is optional.

func LocalCaller added in v0.9.0

func LocalCaller() Caller

LocalCaller is the caller of a single-user application. It is a complete, valid Caller.

func (Caller) Validate added in v0.9.0

func (c Caller) Validate() error

Validate reports a caller with no identity or an unknown kind. An anonymous caller may have an empty ID.

type CallerKind added in v0.9.0

type CallerKind string

CallerKind classifies who is making a request.

const (
	// CallerHuman is a signed-in person.
	CallerHuman CallerKind = "human"
	// CallerService is an automation identity, such as an API key.
	CallerService CallerKind = "service"
	// CallerAnonymous is an unauthenticated request.
	CallerAnonymous CallerKind = "anonymous"
	// CallerLocal is the single user of a local, single-user application.
	CallerLocal CallerKind = "local"
)

type CatalogEvidence added in v0.3.0

type CatalogEvidence struct {
	Status     CatalogEvidenceStatus `json:"status"`
	Models     []ModelInfo           `json:"models,omitempty"`
	ObservedAt time.Time             `json:"observed_at,omitempty"`
}

CatalogEvidence records what a provider advertised. Discovery alone does not prove that any model can successfully perform inference.

type CatalogEvidenceStatus added in v0.3.0

type CatalogEvidenceStatus string
const (
	CatalogNotProbed  CatalogEvidenceStatus = "not_probed"
	CatalogDiscovered CatalogEvidenceStatus = "discovered"
	CatalogEmpty      CatalogEvidenceStatus = "empty"
	CatalogFailed     CatalogEvidenceStatus = "failed"
)

type CatalogKey added in v0.9.0

type CatalogKey struct {
	Instance      string
	CredentialKey string
}

CatalogKey identifies one stored catalog: a provider instance and the key of the credential that discovered it. A catalog depends on the credential, not on the caller: callers sharing a system credential share its catalog, while a personal subscription gets its own. An empty CredentialKey is the catalog of a provider discovered without a credential.

type CatalogRecord added in v0.9.0

type CatalogRecord struct {
	Evidence CatalogEvidence
	Revision string
}

CatalogRecord is a stored catalog and its revision. The revision is opaque and changes on every save.

type CatalogStore added in v0.9.0

type CatalogStore interface {
	// Load returns the stored record, or ErrCatalogNotFound.
	Load(ctx context.Context, key CatalogKey) (CatalogRecord, error)
	// Save stores evidence and returns its new revision.
	Save(ctx context.Context, key CatalogKey, evidence CatalogEvidence) (revision string, err error)
}

CatalogStore keeps discovered catalogs where every process that shares the store can read them.

Save must be atomic with respect to Load in any process: a reader sees the previous record or the new one, never a mix. Because the revision changes on every save, a Runtime that cached a catalog can tell another process's write from its own. The catalogtest package verifies these guarantees.

type CompletionProbeEvidence added in v0.3.0

type CompletionProbeEvidence struct {
	Target      Target                `json:"target"`
	Status      CompletionProbeStatus `json:"status"`
	ObservedAt  time.Time             `json:"observed_at,omitempty"`
	Latency     time.Duration         `json:"latency,omitempty"`
	FailureCode string                `json:"failure_code,omitempty"`
}

CompletionProbeEvidence records inference evidence for one exact target.

func (CompletionProbeEvidence) InferenceVerified added in v0.3.0

func (e CompletionProbeEvidence) InferenceVerified() bool

type CompletionProbeStatus added in v0.3.0

type CompletionProbeStatus string
const (
	CompletionNotProbed CompletionProbeStatus = "not_probed"
	CompletionVerified  CompletionProbeStatus = "verified"
	CompletionFailed    CompletionProbeStatus = "failed"
)

type Config

type Config struct {
	Providers    map[string]ProviderConfig `json:"providers"`
	Routes       map[string]RouteConfig    `json:"routes"`
	DefaultRoute string                    `json:"default_route,omitempty"`

	// Pluggable extension hooks
	Authenticator      Authenticator
	PolicyGate         PolicyGate
	CredentialResolver CredentialResolver
	UsageHook          UsageHook
}

Config configures the core LLM Gateway engine.

type Credential

type Credential struct {
	APIKey             string            `json:"api_key,omitempty"`
	Token              string            `json:"token,omitempty"`
	ConnectionID       string            `json:"connection_id,omitempty"`
	CredentialRevision int64             `json:"credential_revision,omitempty"`
	Headers            map[string]string `json:"headers,omitempty"`
	// AccountID identifies the upstream account the credential belongs to,
	// such as the ChatGPT account a Codex token acts for. Empty when unknown.
	AccountID string `json:"account_id,omitempty"`
	// TokenType names the kind of credential: TokenTypeAPIKey for a static
	// key, usually "Bearer" for an OAuth token, or a kind the provider
	// defines, such as a service account.
	TokenType string `json:"token_type,omitempty"`
	// Metadata carries provider-specific values, such as a project ID.
	// Providers read it and never write it, because a credential may serve
	// concurrent requests. It may hold secrets, such as a client secret, so
	// it never serializes and its values never print.
	Metadata map[string]string `json:"-"`
}

Credential contains authentication secrets for an upstream provider.

fmt and slog print whether each secret is set, never its value. JSON encoding carries every field but Metadata, so slog's JSON handler reveals the secrets of a credential nested in another logged value.

func CredentialFromRecord added in v0.9.0

func CredentialFromRecord(key string, record tokenstore.Record) *Credential

CredentialFromRecord converts a stored record into the credential a provider receives. The access token becomes APIKey for an API-key record and Token otherwise, and the key becomes ConnectionID. AccountID, TokenType and Metadata carry over, so a provider can address the account, tell what kind of credential it holds and read its provider-specific values. Metadata is copied, so the credential and the record never share a map. The refresh token stays behind, because only tokenstore.Coordinator refreshes. Record revisions are opaque strings, so CredentialRevision stays zero and evidence carries the revision instead.

func (Credential) Format added in v0.10.0

func (c Credential) Format(state fmt.State, verb rune)

Format keeps every verb from printing secrets. Without it, fmt uses String and GoString only for %v, %s, %q, %x and %X, and prints the fields for any other verb, secrets included. Only %p of a value and %w escape it: fmt reports those as bad verbs and prints the fields without calling a method.

func (Credential) GoString added in v0.10.0

func (c Credential) GoString() string

GoString keeps %#v from printing secrets.

func (Credential) LogValue added in v0.10.0

func (c Credential) LogValue() slog.Value

LogValue keeps structured logging from printing secrets. Metadata keys are sorted, so equal credentials log alike.

func (Credential) String added in v0.10.0

func (c Credential) String() string

String describes the credential without its secrets. The API key, the token and the headers print only whether they are set, and each Metadata key prints with only whether its value is set.

type CredentialResolver

type CredentialResolver interface {
	Resolve(ctx context.Context, principal *Principal, providerID string) (*Credential, error)
}

CredentialResolver resolves upstream credentials for a principal and provider.

type CredentialStore added in v0.9.0

type CredentialStore interface {
	tokenstore.Store
	// Resolve returns the key of the credential that serves caller on
	// instance, or ErrNoCredential.
	Resolve(ctx context.Context, caller Caller, instance string) (key string, err error)
}

CredentialStore holds the credentials a Runtime uses.

It is the llm-provider-auth token store plus Resolve. The store's Lease must exclude every process that shares it: a file store holds an OS advisory lock on a separate lock file, and a database store holds a lease row with a holder and an expiry, never a transaction held across a refresh.

Resolve names the credential for a caller and a provider instance. Which credential applies is product policy. Keeping it fresh is not: the Runtime refreshes OAuth credentials through tokenstore.Coordinator, which never lets a refresh change the account.

type Disposition added in v0.9.0

type Disposition string

Disposition is what a failure permits a router to do next.

const (
	// DispositionRetryable permits retrying the same target, and failing over.
	DispositionRetryable Disposition = "retryable"
	// DispositionFailover permits trying the next target but not repeating
	// this one.
	DispositionFailover Disposition = "failover"
	// DispositionTerminal ends the request: no target would serve it.
	DispositionTerminal Disposition = "terminal"
)

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine is the core LLM Gateway routing and proxy engine. It implements http.Handler and can be mounted directly on any router.

func NewEngine

func NewEngine(cfg Config) *Engine

func (*Engine) RegisterProvider

func (e *Engine) RegisterProvider(id string, provider any)

RegisterProvider registers an active provider backend.

func (*Engine) ServeHTTP

func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler.

type EvidenceSink added in v0.9.0

type EvidenceSink interface {
	Record(ctx context.Context, evidence AccountEvidence)
}

EvidenceSink receives account evidence. Record must neither fail nor delay the operation it describes: a sink that persists evidence buffers or drops.

type EvidenceSinkFunc added in v0.9.0

type EvidenceSinkFunc func(ctx context.Context, evidence AccountEvidence)

EvidenceSinkFunc adapts a function to EvidenceSink.

func (EvidenceSinkFunc) Record added in v0.9.0

func (f EvidenceSinkFunc) Record(ctx context.Context, evidence AccountEvidence)

Record implements EvidenceSink.

type FreshnessStatus added in v0.3.0

type FreshnessStatus string
const (
	FreshnessUnknown FreshnessStatus = "unknown"
	FreshnessFresh   FreshnessStatus = "fresh"
	FreshnessExpired FreshnessStatus = "expired"
)

type GenerateImagesRequest added in v0.6.0

type GenerateImagesRequest struct {
	Model  string `json:"model"`
	Prompt string `json:"prompt"`
	Count  int    `json:"count,omitempty"`
}

GenerateImagesRequest is the storage-neutral input for image synthesis. Count is a caller-side result bound; providers may return fewer images.

type GenerateImagesResult added in v0.6.0

type GenerateImagesResult struct {
	Images []GeneratedImage `json:"images"`
	Usage  map[string]any   `json:"usage,omitempty"`
}

GenerateImagesResult contains generated bytes and provider-native usage.

type GeneratedImage added in v0.6.0

type GeneratedImage struct {
	Data     []byte `json:"-"`
	MimeType string `json:"mime_type"`
}

GeneratedImage contains one decoded inline image returned by a provider.

type ImageGenerator added in v0.6.0

type ImageGenerator interface {
	GenerateImages(context.Context, GenerateImagesRequest, *Credential) (GenerateImagesResult, error)
}

ImageGenerator is implemented by providers with a typed image-generation operation. It makes no assumptions about credential or image storage.

type Loss added in v0.9.0

type Loss = translate.Loss

Loss is one compatibility finding from translating between surfaces or from adapting a request to a provider. It is llm-translate's type, so both kinds of finding combine in one report.

func StreamLosses added in v0.9.0

func StreamLosses(stream StreamIter) []Loss

StreamLosses returns the losses a stream reports, or nil for a stream that does not translate.

type LossAction added in v0.9.0

type LossAction string

LossAction is what a loss policy does with one loss.

const (
	LossAllow  LossAction = "allow"
	LossReject LossAction = "reject"
)

type LossPolicy added in v0.9.0

type LossPolicy struct {
	Rules []LossRule
}

LossPolicy decides which translation and adaptation losses a product accepts.

Rules apply in order and the first match decides. A loss that no rule matches is rejected unless it is advisory, so an unknown severity counts as material. Allowed losses are still reported to the caller.

func (LossPolicy) Check added in v0.9.0

func (p LossPolicy) Check(losses []Loss) error

Check returns a *LossPolicyError when the policy rejects any loss.

func (LossPolicy) Decide added in v0.9.0

func (p LossPolicy) Decide(loss Loss) LossAction

Decide returns the action for one loss.

func (LossPolicy) Rejected added in v0.9.0

func (p LossPolicy) Rejected(losses []Loss) []Loss

Rejected returns the losses the policy rejects, in report order.

func (LossPolicy) Validate added in v0.9.0

func (p LossPolicy) Validate() error

Validate reports a malformed rule.

type LossPolicyError added in v0.9.0

type LossPolicyError struct {
	Losses []Loss
}

LossPolicyError reports losses a policy rejected. Another target may serve the surface natively, so it permits failover.

func (*LossPolicyError) Error added in v0.9.0

func (e *LossPolicyError) Error() string

func (*LossPolicyError) ProviderErrorClassification added in v0.9.0

func (e *LossPolicyError) ProviderErrorClassification() ProviderErrorClassification

ProviderErrorClassification permits failover without marking the provider unhealthy.

type LossReporter added in v0.9.0

type LossReporter interface {
	Losses() []Loss
}

LossReporter is implemented by streams that translate. Losses returns the request-side losses before the first frame and adds response-side losses as frames are translated; the report is complete once Next returns io.EOF.

type LossRule added in v0.9.0

type LossRule struct {
	// Path is a glob over the dot-separated loss path. "*" matches exactly one
	// segment, "**" matches any number of segments including none, and any
	// other segment matches literally. An empty Path matches every loss.
	Path string
	// Class and Severity narrow the rule. Empty matches any value.
	Class    translate.LossClass
	Severity translate.LossSeverity
	Action   LossAction
}

LossRule matches losses and decides them.

type MemoryCatalogStore added in v0.9.0

type MemoryCatalogStore struct {
	// contains filtered or unexported fields
}

MemoryCatalogStore is the in-memory reference CatalogStore.

func NewMemoryCatalogStore added in v0.9.0

func NewMemoryCatalogStore() *MemoryCatalogStore

NewMemoryCatalogStore returns an empty store.

func (*MemoryCatalogStore) Load added in v0.9.0

Load implements CatalogStore.

func (*MemoryCatalogStore) Save added in v0.9.0

func (s *MemoryCatalogStore) Save(ctx context.Context, key CatalogKey, evidence CatalogEvidence) (string, error)

Save implements CatalogStore.

type MemoryCredentialStore added in v0.9.0

type MemoryCredentialStore struct {
	*tokenstore.Memory
	// contains filtered or unexported fields
}

MemoryCredentialStore is the in-memory reference CredentialStore: tokenstore.Memory plus a resolution table. Resolve prefers a binding for the exact caller and falls back to the instance's shared binding, the way a product prefers a user's own credential over a system one.

func NewMemoryCredentialStore added in v0.9.0

func NewMemoryCredentialStore() *MemoryCredentialStore

NewMemoryCredentialStore returns an empty store.

func (*MemoryCredentialStore) Bind added in v0.9.0

func (s *MemoryCredentialStore) Bind(caller Caller, instance, key string)

Bind makes key the credential of caller on instance.

func (*MemoryCredentialStore) BindShared added in v0.9.0

func (s *MemoryCredentialStore) BindShared(instance, key string)

BindShared makes key the credential of every caller on instance that has no binding of its own.

func (*MemoryCredentialStore) Resolve added in v0.9.0

func (s *MemoryCredentialStore) Resolve(ctx context.Context, caller Caller, instance string) (string, error)

Resolve implements CredentialStore.

type MemoryEvidenceSink added in v0.9.0

type MemoryEvidenceSink struct {
	// contains filtered or unexported fields
}

MemoryEvidenceSink is the in-memory reference EvidenceSink.

func (*MemoryEvidenceSink) Record added in v0.9.0

func (s *MemoryEvidenceSink) Record(_ context.Context, evidence AccountEvidence)

Record implements EvidenceSink.

func (*MemoryEvidenceSink) Records added in v0.9.0

func (s *MemoryEvidenceSink) Records() []AccountEvidence

Records returns a copy of everything recorded, oldest first.

type ModelCapabilities added in v0.3.0

type ModelCapabilities struct {
	SchemaVersion     int                        `json:"schema_version"`
	Operations        ModelOperationCapabilities `json:"operations"`
	Surfaces          ModelSurfaceCapabilities   `json:"surfaces"`
	Inputs            ModelInputCapabilities     `json:"inputs"`
	Tools             Support                    `json:"tools"`
	Reasoning         Support                    `json:"reasoning"`
	StructuredOutput  Support                    `json:"structured_output"`
	Streaming         Support                    `json:"streaming"`
	StatefulResponses Support                    `json:"stateful_responses"`
	Limits            ModelCapabilityLimits      `json:"limits"`
	Provenance        ModelCapabilityProvenance  `json:"provenance"`
	Freshness         ModelCapabilityFreshness   `json:"freshness"`
}

ModelCapabilities is the bounded version 1 shared model capability contract.

func (ModelCapabilities) OperationCompatibility added in v0.3.0

func (c ModelCapabilities) OperationCompatibility(operation ModelOperation) Support

OperationCompatibility returns unknown for both unreported capabilities and operation values outside this schema version.

func (ModelCapabilities) SurfaceCompatibility added in v0.3.0

func (c ModelCapabilities) SurfaceCompatibility(surface ModelSurface) Support

SurfaceCompatibility returns unknown for both unreported capabilities and surface values outside this schema version.

type ModelCapabilityConfidence added in v0.3.0

type ModelCapabilityConfidence string
const (
	ModelCapabilityConfidenceLow    ModelCapabilityConfidence = "low"
	ModelCapabilityConfidenceMedium ModelCapabilityConfidence = "medium"
	ModelCapabilityConfidenceHigh   ModelCapabilityConfidence = "high"
)

type ModelCapabilityFreshness added in v0.3.0

type ModelCapabilityFreshness struct {
	DiscoveredAt *time.Time `json:"discovered_at,omitempty"`
	VerifiedAt   *time.Time `json:"verified_at,omitempty"`
	ExpiresAt    *time.Time `json:"expires_at,omitempty"`
}

func (ModelCapabilityFreshness) IsFresh added in v0.3.0

func (f ModelCapabilityFreshness) IsFresh(at time.Time) bool

func (ModelCapabilityFreshness) Status added in v0.3.0

Status reports unknown when no expiry was supplied. Expiry is inclusive: a capability is expired at its expires_at instant.

type ModelCapabilityLimits added in v0.3.0

type ModelCapabilityLimits struct {
	ContextTokens   *int64 `json:"context_tokens,omitempty"`
	MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"`
}

ModelCapabilityLimits uses pointers so an unknown limit is distinct from a provider-reported numeric value.

type ModelCapabilityProvenance added in v0.3.0

type ModelCapabilityProvenance struct {
	Source     ModelCapabilitySource     `json:"source"`
	Confidence ModelCapabilityConfidence `json:"confidence"`
}

type ModelCapabilitySource added in v0.3.0

type ModelCapabilitySource string
const (
	ModelCapabilitySourceUpstreamReported ModelCapabilitySource = "upstream_reported"
	ModelCapabilitySourceRegistryStatic   ModelCapabilitySource = "registry_static"
	ModelCapabilitySourceModelsDev        ModelCapabilitySource = "models_dev"
	ModelCapabilitySourceInferred         ModelCapabilitySource = "inferred"
	ModelCapabilitySourceOperatorOverride ModelCapabilitySource = "operator_override"
)

type ModelInfo

type ModelInfo struct {
	ID            string             `json:"id"`
	Object        string             `json:"object"`
	Created       int64              `json:"created"`
	OwnedBy       string             `json:"owned_by"`
	Description   string             `json:"description,omitempty"`
	Tags          []string           `json:"tags,omitempty"`
	APIEligible   *bool              `json:"api_eligible,omitempty"`
	APIVisibility string             `json:"api_visibility,omitempty"`
	SupportedAPIs []string           `json:"supported_apis,omitempty"`
	Capabilities  *ModelCapabilities `json:"capabilities,omitempty"`
}

ModelInfo describes an available upstream model or alias.

type ModelInputCapabilities added in v0.3.0

type ModelInputCapabilities struct {
	Text  Support `json:"text"`
	Image Support `json:"image"`
}

type ModelOperation added in v0.3.0

type ModelOperation string
const (
	ModelOperationChat       ModelOperation = "chat"
	ModelOperationEmbeddings ModelOperation = "embeddings"
	ModelOperationImage      ModelOperation = "image"
	ModelOperationAudioIn    ModelOperation = "audio_in"
	ModelOperationAudioOut   ModelOperation = "audio_out"
	ModelOperationVideo      ModelOperation = "video"
	ModelOperationTokenCount ModelOperation = "token_count"
)

type ModelOperationCapabilities added in v0.3.0

type ModelOperationCapabilities struct {
	Chat       Support `json:"chat"`
	Embeddings Support `json:"embeddings"`
	Image      Support `json:"image"`
	AudioIn    Support `json:"audio_in"`
	AudioOut   Support `json:"audio_out"`
	Video      Support `json:"video"`
	TokenCount Support `json:"token_count"`
}

type ModelSurface added in v0.3.0

type ModelSurface string
const (
	ModelSurfaceChatCompletions ModelSurface = "chat_completions"
	ModelSurfaceResponses       ModelSurface = "responses"
	ModelSurfaceMessages        ModelSurface = "messages"

	// Non-chat surfaces. Their request and response bodies are not always
	// JSON: speech-to-text uploads multipart form data, and speech, image and
	// video responses are binary. The capabilities schema reports no
	// compatibility for them yet.
	ModelSurfaceEmbeddings          ModelSurface = "embeddings"
	ModelSurfaceAudioTranscriptions ModelSurface = "audio_transcriptions"
	ModelSurfaceAudioSpeech         ModelSurface = "audio_speech"
	ModelSurfaceImages              ModelSurface = "images"
	ModelSurfaceVideos              ModelSurface = "videos"
)

type ModelSurfaceCapabilities added in v0.3.0

type ModelSurfaceCapabilities struct {
	ChatCompletions Support `json:"chat_completions"`
	Responses       Support `json:"responses"`
	Messages        Support `json:"messages"`
}

type PolicyGate

type PolicyGate interface {
	Allows(ctx context.Context, principal *Principal, target Target) (bool, string)
}

PolicyGate controls whether a principal is authorized to access a given provider/model target.

type Principal deprecated

type Principal struct {
	ID        string         `json:"id"`
	Type      string         `json:"type"` // "user", "api_key", "anonymous", "service"
	Name      string         `json:"name,omitempty"`
	ProjectID string         `json:"project_id,omitempty"`
	Metadata  map[string]any `json:"metadata,omitempty"`
}

Principal represents the authenticated caller making a request.

Deprecated: new APIs take Caller, and Principal.Caller converts. Principal and the Engine hooks that use it move to Caller in the next minor release.

func (*Principal) Caller deprecated added in v0.9.0

func (p *Principal) Caller() Caller

Caller converts a Principal to its Caller.

Deprecated: Principal is replaced by Caller and will be removed in the next minor release. Its Type maps onto a CallerKind: "user" is human, "api_key" and "service" are service, and an empty or "anonymous" type is anonymous.

type Provider added in v0.9.0

type Provider interface {
	// NativeSurfaces lists the surfaces model serves without translation.
	NativeSurfaces(model string) []ModelSurface
	// Invoke performs one non-streaming operation.
	Invoke(ctx context.Context, request Request) (Response, error)
	// Stream performs one streaming operation. Each frame is one complete
	// SSE record of the surface's stream.
	Stream(ctx context.Context, request Request) (StreamIter, error)
	// ListModels returns the provider's catalog for the credential.
	ListModels(ctx context.Context, credential *Credential) ([]ModelInfo, error)
}

Provider performs wire-level operations on the surfaces it serves natively.

A request for any other surface fails with a *SurfaceError; a translation adapter in front of the provider serves other surfaces. Implementations honour ctx cancellation and take credentials only from the request.

type ProviderAdapter added in v0.3.0

type ProviderAdapter struct {
	ValidateAuthentication ProviderAuthenticationValidator
	DiscoverModels         ProviderModelDiscoverer
	SelectProbeTargets     ProviderProbeSelector
	Complete               ProviderCompletionRuntime
}

ProviderAdapter contains the small provider-specific operations used by the shared connector. Complete is both the probe and reusable runtime path.

type ProviderAuthKind added in v0.3.0

type ProviderAuthKind string

ProviderAuthKind describes how a provider connection authenticates.

const (
	ProviderAuthAPIKey           ProviderAuthKind = "api_key"
	ProviderAuthOAuthDevice      ProviderAuthKind = "oauth_device"
	ProviderAuthOAuthBrowser     ProviderAuthKind = "oauth_browser"
	ProviderAuthServiceAccount   ProviderAuthKind = "service_account"
	ProviderAuthWorkloadIdentity ProviderAuthKind = "workload_identity"
	ProviderAuthOfficialClient   ProviderAuthKind = "official_client"
	ProviderAuthAnonymous        ProviderAuthKind = "anonymous"
)

type ProviderAuthenticationValidator added in v0.3.0

type ProviderAuthenticationValidator func(context.Context, ProviderConnection) error

type ProviderCompletionRuntime added in v0.3.0

type ProviderCompletionRuntime func(context.Context, ProviderConnection, Target, map[string]any) (map[string]any, error)

type ProviderConfig

type ProviderConfig struct {
	Type          string            `json:"type"`                     // "openai_compatible", "anthropic", "googleai", "ollama", "github_copilot", "codex", "edgetts"
	BaseURL       string            `json:"base_url,omitempty"`       // Upstream base endpoint
	APIKey        string            `json:"api_key,omitempty"`        // Static API key or token
	Timeout       time.Duration     `json:"timeout,omitempty"`        // Request timeout
	Headers       map[string]string `json:"headers,omitempty"`        // Extra HTTP headers
	AllowedModels []string          `json:"allowed_models,omitempty"` // Whitelist of models
	Disabled      bool              `json:"disabled,omitempty"`       // Disable provider
}

ProviderConfig configures a single upstream provider backend.

type ProviderConnectRequest added in v0.3.0

type ProviderConnectRequest struct {
	Connection        ProviderConnection      `json:"connection"`
	PublicationPolicy TargetPublicationPolicy `json:"publication_policy"`
	// AuthenticationValidated permits callers that established authentication
	// before Connect to omit an adapter authentication validator.
	AuthenticationValidated bool `json:"authentication_validated,omitempty"`
}

type ProviderConnectResult added in v0.3.0

type ProviderConnectResult struct {
	Connection ProviderConnection        `json:"connection"`
	Catalog    CatalogEvidence           `json:"catalog"`
	Probes     []CompletionProbeEvidence `json:"probes,omitempty"`
	Health     ProviderHealthEvidence    `json:"health"`
	Targets    []Target                  `json:"targets,omitempty"`
}

ProviderConnectResult is the complete, persistence-agnostic outcome of provider onboarding.

type ProviderConnection added in v0.3.0

type ProviderConnection struct {
	ID         string                 `json:"id,omitempty"`
	ProviderID string                 `json:"provider_id"`
	Kind       ProviderConnectionKind `json:"kind"`
	AuthKind   ProviderAuthKind       `json:"auth_kind"`
	OwnerID    string                 `json:"owner_id,omitempty"`
	Credential *Credential            `json:"-"`
}

ProviderConnection is the persistence-agnostic description of a configured provider connection. Credential is available to connectors but never JSON encoded.

func (ProviderConnection) Validate added in v0.3.0

func (c ProviderConnection) Validate() error

Validate rejects contradictory connection descriptions. Codex is always a human-owned subscription connection established through device OAuth.

type ProviderConnectionKind added in v0.3.0

type ProviderConnectionKind string

ProviderConnectionKind describes who owns and may use a provider connection.

const (
	ProviderConnectionSystem               ProviderConnectionKind = "system"
	ProviderConnectionPersonal             ProviderConnectionKind = "personal"
	ProviderConnectionPersonalSubscription ProviderConnectionKind = "personal_subscription"
	ProviderConnectionAnonymous            ProviderConnectionKind = "anonymous"
)

type ProviderConnector added in v0.3.0

type ProviderConnector interface {
	Connect(ctx context.Context, request ProviderConnectRequest) (ProviderConnectResult, error)
}

ProviderConnector orchestrates provider-specific authentication, discovery, probing, classification, and exact target publication.

type ProviderError added in v0.9.0

type ProviderError struct {
	Message        string
	Class          ProviderErrorClass
	Classification ProviderErrorClassification
	Cause          error
}

ProviderError is the canonical provider failure.

Message is safe to show a client: it never contains credentials, private endpoints or upstream response bodies. Cause keeps the underlying error for errors.Is and errors.As and is never rendered.

func NewConfigurationError added in v0.9.0

func NewConfigurationError(message string, cause error) *ProviderError

NewConfigurationError reports a provider that cannot run as configured. It permits failover, because another target may be configured correctly, but never marks the provider unhealthy.

func (*ProviderError) Error added in v0.9.0

func (e *ProviderError) Error() string

func (*ProviderError) ProviderErrorClassification added in v0.9.0

func (e *ProviderError) ProviderErrorClassification() ProviderErrorClassification

ProviderErrorClassification returns the routing metadata.

func (*ProviderError) Unwrap added in v0.9.0

func (e *ProviderError) Unwrap() error

type ProviderErrorClass added in v0.3.0

type ProviderErrorClass string
const (
	ProviderErrorNone        ProviderErrorClass = "none"
	ProviderErrorAuth        ProviderErrorClass = "auth"
	ProviderErrorForbidden   ProviderErrorClass = "forbidden"
	ProviderErrorRateLimited ProviderErrorClass = "rate_limited"
	ProviderErrorTransport   ProviderErrorClass = "transport"
	ProviderErrorUpstream    ProviderErrorClass = "upstream"
)
const (
	// ProviderErrorConfiguration is a provider that cannot run as configured.
	ProviderErrorConfiguration ProviderErrorClass = "configuration"
	// ProviderErrorInvalidRequest is a request the provider rejects as
	// malformed; other targets would reject it too.
	ProviderErrorInvalidRequest ProviderErrorClass = "invalid_request"
	// ProviderErrorUnsupported is a request this target cannot serve, such as
	// a surface it lacks or a translation the loss policy rejects.
	ProviderErrorUnsupported ProviderErrorClass = "unsupported"
)

Error classes beyond the upstream causes that health classification reports.

type ProviderErrorClassification added in v0.4.0

type ProviderErrorClassification struct {
	StatusCode       int
	Retryable        bool
	FailoverEligible bool
	CircuitFailure   bool
	RetryAfter       time.Duration
}

ProviderErrorClassification is the provider-independent routing metadata for an operation failure. StatusCode is zero when no HTTP response was received, and RetryAfter is zero when the provider gave no delay. Disposition summarizes what the failure permits.

func ClassifyError added in v0.9.0

func ClassifyError(err error) ProviderErrorClassification

ClassifyError returns the routing metadata of any error. An error that does not classify itself, including a canceled context, is terminal.

func (ProviderErrorClassification) Disposition added in v0.9.0

func (c ProviderErrorClassification) Disposition() Disposition

Disposition summarizes the classification.

type ProviderErrorClassifier added in v0.4.0

type ProviderErrorClassifier interface {
	ProviderErrorClassification() ProviderErrorClassification
}

ProviderErrorClassifier exposes routing metadata without requiring callers to depend on a provider package's concrete error type.

type ProviderFailure added in v0.3.0

type ProviderFailure struct {
	StatusCode int       `json:"status_code,omitempty"`
	RetryAfter string    `json:"retry_after,omitempty"`
	ObservedAt time.Time `json:"observed_at,omitempty"`
	Err        error     `json:"-"`
}

ProviderFailure contains only values needed for classification. Err is never serialized because transport errors may include credentials or private hosts.

type ProviderHealthEvidence added in v0.3.0

type ProviderHealthEvidence struct {
	Status     ProviderHealthStatus `json:"status"`
	ErrorClass ProviderErrorClass   `json:"error_class"`
	Permanent  bool                 `json:"permanent,omitempty"`
	Retryable  bool                 `json:"retryable,omitempty"`
	RetryAfter time.Duration        `json:"retry_after,omitempty"`
	ObservedAt time.Time            `json:"observed_at,omitempty"`
}

func ClassifyProviderFailure added in v0.3.0

func ClassifyProviderFailure(f ProviderFailure) ProviderHealthEvidence

ClassifyProviderFailure maps HTTP and transport outcomes into stable health semantics.

type ProviderHealthStatus added in v0.3.0

type ProviderHealthStatus string
const (
	ProviderHealthUnknown   ProviderHealthStatus = "unknown"
	ProviderHealthHealthy   ProviderHealthStatus = "healthy"
	ProviderHealthDegraded  ProviderHealthStatus = "degraded"
	ProviderHealthUnhealthy ProviderHealthStatus = "unhealthy"
)

type ProviderModelDiscoverer added in v0.3.0

type ProviderModelDiscoverer func(context.Context, ProviderConnection) ([]ModelInfo, error)

type ProviderOperationError added in v0.3.0

type ProviderOperationError struct {
	Failure ProviderFailure
	Op      string
}

ProviderOperationError preserves classification inputs without exposing an upstream response body or transport error through serialized evidence.

func (*ProviderOperationError) Error added in v0.3.0

func (e *ProviderOperationError) Error() string

func (*ProviderOperationError) ProviderErrorClassification added in v0.4.0

func (e *ProviderOperationError) ProviderErrorClassification() ProviderErrorClassification

func (*ProviderOperationError) Unwrap added in v0.3.0

func (e *ProviderOperationError) Unwrap() error

type ProviderOrchestrator added in v0.3.0

type ProviderOrchestrator struct {
	// contains filtered or unexported fields
}

ProviderOrchestrator resolves only explicitly registered adapters. This is particularly important for Codex: its personal subscription OAuth flow must never fall through to anonymous OpenAI-compatible behavior.

func NewProviderOrchestrator added in v0.3.0

func NewProviderOrchestrator() *ProviderOrchestrator

func (*ProviderOrchestrator) Connect added in v0.3.0

func (*ProviderOrchestrator) Register added in v0.3.0

func (o *ProviderOrchestrator) Register(providerID string, adapter ProviderAdapter) error

type ProviderProbeSelector added in v0.3.0

type ProviderProbeSelector func(ProviderConnection, []ModelInfo) []Target

type Request added in v0.9.0

type Request struct {
	Surface     ModelSurface
	Model       string
	Body        []byte
	ContentType string
	Credential  *Credential
}

Request is one wire-level provider operation.

Body is exactly the surface's request body: JSON for the chat surfaces and embeddings, multipart form data for speech-to-text. ContentType names its encoding. The credential is explicit; a provider never looks one up.

func (Request) Validate added in v0.9.0

func (r Request) Validate() error

Validate reports a request that no provider could serve.

type Resolution added in v0.1.1

type Resolution struct {
	Targets  []Target `json:"targets"`
	Category string   `json:"category,omitempty"`
}

Resolution records both the resolved targets and the canonical category name, when the request addressed a category rather than a direct model.

type Response added in v0.9.0

type Response struct {
	Body        []byte
	ContentType string
	Losses      []Loss
}

Response is the result of a non-streaming operation.

Body is the surface's response body, JSON or binary as ContentType says. Losses lists every compatibility loss the operation incurred, including losses the loss policy allowed, so a product can log or label them.

type RouteConfig

type RouteConfig struct {
	Targets     []Target `json:"targets"`               // Ordered targets to try
	Fallback    bool     `json:"fallback,omitempty"`    // Fall back to subsequent targets on error
	Description string   `json:"description,omitempty"` // User-facing description
}

RouteConfig configures an alias (failover chain) across multiple provider targets.

type StaticCredentialResolver

type StaticCredentialResolver struct {
	Credentials map[string]Credential
}

StaticCredentialResolver returns pre-configured credentials from a map.

func (StaticCredentialResolver) Resolve

func (s StaticCredentialResolver) Resolve(ctx context.Context, principal *Principal, providerID string) (*Credential, error)

type StreamIter added in v0.4.0

type StreamIter interface {
	Next() ([]byte, error)
	Close() error
}

StreamIter yields complete SSE frames from an active provider stream.

type Support added in v0.3.0

type Support uint8

Support is an explicitly tri-state capability value. Its zero value is SupportUnknown and marshals as "unknown" rather than false.

const (
	SupportUnknown Support = iota
	SupportSupported
	SupportUnsupported
)

func (Support) IsKnown added in v0.3.0

func (s Support) IsKnown() bool

func (Support) IsSupported added in v0.3.0

func (s Support) IsSupported() bool

func (Support) MarshalJSON added in v0.3.0

func (s Support) MarshalJSON() ([]byte, error)

func (Support) String added in v0.3.0

func (s Support) String() string

func (*Support) UnmarshalJSON added in v0.3.0

func (s *Support) UnmarshalJSON(data []byte) error

type SurfaceError added in v0.9.0

type SurfaceError struct {
	Surface ModelSurface
	Model   string
}

SurfaceError reports a request for a surface the provider does not serve natively. Another target may serve it, so it permits failover.

func (*SurfaceError) Error added in v0.9.0

func (e *SurfaceError) Error() string

func (*SurfaceError) ProviderErrorClassification added in v0.9.0

func (e *SurfaceError) ProviderErrorClassification() ProviderErrorClassification

ProviderErrorClassification permits failover without marking the provider unhealthy.

type Target

type Target struct {
	Provider string `json:"provider"`
	Model    string `json:"model"`
}

Target represents a resolved provider and model.

func PublishExactTargets added in v0.3.0

func PublishExactTargets(providerID string, catalog CatalogEvidence, probes []CompletionProbeEvidence, policy TargetPublicationPolicy) ([]Target, error)

PublishExactTargets converts catalog evidence to exact provider/model targets. Under verification policy, only targets with successful inference evidence publish.

type TargetPublicationPolicy added in v0.3.0

type TargetPublicationPolicy string
const (
	PublishDiscoveredTargets TargetPublicationPolicy = "catalog_discovered"
	PublishVerifiedTargets   TargetPublicationPolicy = "inference_verified"
)

type TransportConfidence added in v0.4.0

type TransportConfidence string
const (
	TransportConfidenceLow    TransportConfidence = "low"
	TransportConfidenceMedium TransportConfidence = "medium"
	TransportConfidenceHigh   TransportConfidence = "high"
)

type TransportDisposition added in v0.4.0

type TransportDisposition string
const (
	TransportNative  TransportDisposition = "native"
	TransportAdapted TransportDisposition = "adapted"
	TransportReject  TransportDisposition = "reject"
)

type TransportInterface added in v0.4.0

type TransportInterface struct {
	Surface ModelSurface `json:"surface"`
	Native  Support      `json:"native"`
}

TransportInterface is an available provider interface. Native records whether using this interface for its named surface preserves native provider semantics; SupportUnsupported therefore means available through adaptation, not unavailable.

type TransportPlan added in v0.4.0

type TransportPlan struct {
	Disposition TransportDisposition  `json:"disposition"`
	Surface     ModelSurface          `json:"surface"`
	Confidence  TransportConfidence   `json:"confidence"`
	Losses      []translate.Loss      `json:"losses,omitempty"`
	Reason      TransportRejectReason `json:"reason,omitempty"`
}

TransportPlan is a deterministic decision over the supplied evidence.

func PlanTransport added in v0.4.0

func PlanTransport(request TransportPlanRequest) TransportPlan

PlanTransport selects a native interface when one is confirmed, preserves unknown evidence as eligible at low confidence, and otherwise considers an explicitly reported adaptation. It performs no I/O and applies no gateway or provider policy.

type TransportPlanRequest added in v0.4.0

type TransportPlanRequest struct {
	Operation            ModelOperation       `json:"operation"`
	Surface              ModelSurface         `json:"surface"`
	EvaluatedAt          time.Time            `json:"evaluated_at"`
	ExactTarget          bool                 `json:"exact_target"`
	Capabilities         ModelCapabilities    `json:"capabilities"`
	Interfaces           []TransportInterface `json:"interfaces"`
	Requirement          TransportRequirement `json:"requirement"`
	TranslationEvaluated bool                 `json:"translation_evaluated"`
	Translation          translate.Report     `json:"translation"`
}

TransportPlanRequest contains only evidence needed to choose a transport. Translation describes the conversion that would be used by an adapted plan.

type TransportRejectReason added in v0.4.0

type TransportRejectReason string
const (
	TransportRejectInvalidRequirement     TransportRejectReason = "invalid_requirement"
	TransportRejectOperationUnsupported   TransportRejectReason = "operation_unsupported"
	TransportRejectNoInterface            TransportRejectReason = "no_interface"
	TransportRejectNativeRequired         TransportRejectReason = "native_required"
	TransportRejectExactTargetRequired    TransportRejectReason = "exact_target_required"
	TransportRejectNativeUnconfirmed      TransportRejectReason = "native_unconfirmed"
	TransportRejectTranslationUnevaluated TransportRejectReason = "translation_not_evaluated"
	TransportRejectTranslationLoss        TransportRejectReason = "translation_loss"
)

type TransportRequirement added in v0.4.0

type TransportRequirement string

TransportRequirement constrains whether a request may use adaptation.

const (
	TransportRequirementAny         TransportRequirement = "any"
	TransportRequirementNative      TransportRequirement = "native"
	TransportRequirementTransparent TransportRequirement = "transparent"
)

type UsageHook

type UsageHook interface {
	RecordUsage(ctx context.Context, record UsageRecord)
}

UsageHook receives telemetry records after each completed request.

type UsageHookFunc

type UsageHookFunc func(ctx context.Context, record UsageRecord)

UsageHookFunc is a functional adapter for UsageHook.

func (UsageHookFunc) RecordUsage

func (f UsageHookFunc) RecordUsage(ctx context.Context, record UsageRecord)

type UsageRecord

type UsageRecord struct {
	RequestID    string        `json:"request_id"`
	PrincipalID  string        `json:"principal_id,omitempty"`
	ProjectID    string        `json:"project_id,omitempty"`
	Provider     string        `json:"provider"`
	Model        string        `json:"model"`
	InputTokens  int           `json:"input_tokens"`
	OutputTokens int           `json:"output_tokens"`
	Duration     time.Duration `json:"duration"`
	Stream       bool          `json:"stream"`
	StatusCode   int           `json:"status_code"`
	Error        string        `json:"error,omitempty"`
}

UsageRecord holds metrics and token counts from a completed LLM call.

Directories

Path Synopsis
Package catalogtest is the conformance suite for core.CatalogStore implementations.
Package catalogtest is the conformance suite for core.CatalogStore implementations.
Package execution provides the primitives failover is built from: a HealthTracker that breaks circuits and cools down instances, and executors that try candidates in order and never fail over once output has reached the caller.
Package execution provides the primitives failover is built from: a HealthTracker that breaks circuits and cools down instances, and executors that try candidates in order and never fail over once output has reached the caller.
Package oauthflow runs server-side OAuth flows for products that sign users in to LLM providers: browser authorization codes with PKCE, device authorization, and codes the owner pastes back.
Package oauthflow runs server-side OAuth flows for products that sign users in to LLM providers: browser authorization codes with PKCE, device authorization, and codes the owner pastes back.
oauthflowtest
Package oauthflowtest is the conformance suite for oauthflow.FlowStore implementations.
Package oauthflowtest is the conformance suite for oauthflow.FlowStore implementations.
zen
Package zen implements the reusable, storage-neutral OpenCode Zen anonymous admission contract.
Package zen implements the reusable, storage-neutral OpenCode Zen anonymous admission contract.
Package runtime provides Runtime, the one value that owns an embedding product's provider state: the provider registry, the provider cache, the credential refresh coordinators, the catalog cache and provider health.
Package runtime provides Runtime, the one value that owns an embedding product's provider state: the provider registry, the provider cache, the credential refresh coordinators, the catalog cache and provider health.
Package translation serves surfaces a provider lacks by translating through llm-translate.
Package translation serves surfaces a provider lacks by translating through llm-translate.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL