config

package
v0.2.7 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package config loads kram-gateway's YAML configuration: which upstream providers exist, how they're grouped into fallback combos, and which routing strategy each combo uses.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Save

func Save(cfg *Config, path string) error

Save writes cfg as YAML to path, creating parent directories as needed. Writes to a temporary file first and renames it into place — on POSIX this rename is atomic; os.Rename also fails if path already exists on Windows, so the pre-existing file is removed first (there's a brief window where neither the old nor new file exists, but that's strictly better than a reader ever observing a half-written file, which the temp-file-then-rename alone already prevents on POSIX).

Types

type ComboConfig

type ComboConfig struct {
	ID              string             `yaml:"id"`
	Strategy        string             `yaml:"strategy"` // "round-robin" in v0; see internal/router for the full set
	Providers       []string           `yaml:"providers"`
	StrategyOptions StrategyOptions    `yaml:"strategy_options,omitempty"`
	Response        ResponseGateConfig `yaml:"response,omitempty"`
}

ComboConfig is a named, ordered fallback chain of providers plus the strategy used to pick among the healthy ones.

type Config

type Config struct {
	Host      string           `yaml:"host"`
	Port      int              `yaml:"port"`
	Providers []ProviderConfig `yaml:"providers"`
	Combos    []ComboConfig    `yaml:"combos"`
	// DefaultCombo is used when a request's "model" doesn't match a combo ID.
	DefaultCombo string `yaml:"default_combo"`
}

Config is the top-level gateway configuration.

func Load

func Load(path string) (*Config, error)

Load reads and validates a YAML config file.

type ProviderConfig

type ProviderConfig struct {
	ID string `yaml:"id"`
	// Kind selects the adapter: "anthropic", "gemini", "openai-compat", or
	// "openai-responses" (the ChatGPT-login-only Codex backend — see
	// internal/provider/openai_responses.go).
	Kind string `yaml:"kind"`
	// BaseURL is the upstream API root. Optional for kinds with a
	// well-known default (anthropic, gemini, openai-responses).
	BaseURL string `yaml:"base_url,omitempty"`
	// APIKeyEnv names the environment variable holding the credential —
	// for AuthMode "oauth" it's used purely as the lookup key into the
	// credentials store's OAuth token map, not as a real env var.
	APIKeyEnv string `yaml:"api_key_env"`
	// AuthMode selects how the gateway resolves this provider's
	// credential. Empty (the default) is today's behavior: read
	// APIKeyEnv from the process environment once at startup and use it
	// for the provider's lifetime. "oauth" means the credential is a
	// refreshable token in internal/credentials' OAuth store, resolved
	// live on every request (see internal/gateway.Run) since it can
	// expire mid-session — see internal/credentials.Store.Resolve.
	AuthMode string `yaml:"auth_mode,omitempty"`
	// KeyOptional means APIKey should return an empty string instead of an
	// error when APIKeyEnv isn't set — true only for
	// internal/customprovider entries, most of which point at a local/LAN
	// server with no auth at all. Every other provider keeps the strict
	// default: an unset env var is a real misconfiguration worth failing
	// loudly on (a clear startup error beats a confusing 401 later).
	KeyOptional bool `yaml:"key_optional,omitempty"`
	// Model is the upstream model ID to request, if it should be pinned
	// regardless of what the client asked for. Empty means passthrough.
	Model string `yaml:"model,omitempty"`
	// SupportsImages declares whether this provider's model accepts image
	// input. Callers must check this (via /admin/status) before attaching
	// images — the gateway never guesses.
	SupportsImages bool `yaml:"supports_images,omitempty"`
	// SupportsTools declares whether this provider's model can be sent
	// tool/function definitions. Kram's agent loop skips providers that
	// don't when a request requires tool calling.
	SupportsTools bool `yaml:"supports_tools,omitempty"`
	// QualityHint is an optional, explicitly user-configured 0..1 signal
	// feeding the "quality" scoring factor (see internal/router) —
	// deliberately never inferred or fabricated by Kram itself, since
	// there is no real per-provider quality measurement to derive it
	// from. Zero means "no opinion", which the scorer treats as neutral
	// (0.5), not "worst possible" — see DECISIONS.md.
	QualityHint float64 `yaml:"quality_hint,omitempty"`
}

ProviderConfig describes one upstream LLM backend.

func (ProviderConfig) APIKey

func (p ProviderConfig) APIKey() (string, error)

APIKey resolves the provider's credential from its configured env var.

type ResponseGateConfig

type ResponseGateConfig struct {
	// RejectEmpty rejects a response with neither text content nor tool
	// calls.
	RejectEmpty bool `yaml:"reject_empty,omitempty"`
	// RequireTerminal rejects a stream that never produced a proper
	// finish signal (e.g. a connection that was cut mid-stream) even if
	// it carried some content.
	RequireTerminal bool `yaml:"require_terminal,omitempty"`
	// MinContentLength rejects a text response shorter than this many
	// characters (tool-call-only responses are exempt — a short "ok,
	// calling the tool now" isn't what this guards against).
	MinContentLength int `yaml:"min_content_length,omitempty"`
	// ForbiddenSubstrings rejects a response whose content contains any
	// of these — for masked upstream errors that come back as HTTP 200
	// with an error message as the body, not for filtering legitimate
	// model output.
	ForbiddenSubstrings []string `yaml:"forbidden_substrings,omitempty"`
}

ResponseGateConfig configures deterministic, technical validation of an otherwise-successful response before it's allowed to end the fallback chain — see router.ResponseGate. Every field is opt-in; an absent response block disables gating entirely (the v0 behavior: any technically-successful response is accepted).

type StrategyOptions

type StrategyOptions struct {
	// Sticky pins a run (see router.RunKey) to its winning provider
	// across tool round-trips, only used by the weighted (smart/quality/
	// fast/cheap/reliable/custom) strategy family. Defaults to true for
	// that family if unset — see DECISIONS.md, "Sticky by default".
	Sticky *bool `yaml:"sticky,omitempty"`
	// LKGPBoost is the additive score bonus (0..1) a candidate gets when
	// it's the combo's current last-known-good provider, on top of its
	// own weighted score. 0 (the zero value) if unset would disable the
	// boost entirely, so an unset field falls back to a small nonzero
	// default instead — see router.defaultLKGPBoost.
	LKGPBoost *float64 `yaml:"lkgp_boost,omitempty"`
	// Exploration is the probability (0..1) of picking a uniformly random
	// eligible candidate as the leader instead of the top-ranked one, so
	// non-winning candidates still occasionally get real telemetry — see
	// DECISIONS.md, "Exploration". Small and conservative by default.
	Exploration *float64 `yaml:"exploration,omitempty"`
	// Weights overrides the weighted strategy's per-factor weights
	// (health, reliability, latency, quality, cache_affinity, priority).
	// Any factor not mentioned keeps its preset's weight; values are
	// normalized automatically, so they don't need to sum to any
	// particular total.
	Weights map[string]float64 `yaml:"weights,omitempty"`
}

StrategyOptions tunes a combo's routing strategy — every field is optional, and an absent strategy_options block (the whole existing v0 config shape) means "use the strategy's own defaults", never a required section. Pointers distinguish "not set, use the default" from "set to the zero value", which matters for Sticky in particular (explicitly disabling stickiness is a real, different choice from never mentioning it).

Jump to

Keyboard shortcuts

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