Documentation
¶
Overview ¶
Package base defines the unified provider abstraction shared across all PromptKit provider types (inference, TTS, STT, embedding, image generation).
Every provider implements Provider for cross-cutting concerns (identity, pricing, lifecycle) and exactly one of the per-type interfaces below for capability-specific operations.
Package base — canonical token-unit vocabulary shared by all inference providers and their pricing tables. The pricing engine still accepts any unit string; these constants exist so providers and price items never drift.
Index ¶
- Constants
- func APIKeyFromCredential(c credentials.Credential) string
- func AggregateCost(parts ...*types.CostInfo) types.CostInfo
- func CostInfoToMetaMap(ci *types.CostInfo) map[string]any
- func GetTyped[T Provider](r *Registry, name string, typ ProviderType) (T, error)
- func MakeCostInfo(desc *PricingDescriptor, providerName string, capability ProviderType, ...) *types.CostInfo
- func NewHTTPService(apiKey string, defaults HTTPServiceDefaults, opts ...HTTPServiceOption) (*Implementation, *HTTPServiceFields)
- func PriceUsage(desc *PricingDescriptor, providerName string, capability ProviderType, ...) types.CostInfo
- func ReadAllAudio(stream TTSStream) ([]byte, *types.CostInfo, error)
- func ResolveCredential(ctx context.Context, providerType string, cfgDir string, ...) (credentials.Credential, error)
- func StartCapabilitySpan(ctx context.Context, tracer trace.Tracer, args *SpanArgs) (context.Context, trace.Span)
- type CapabilitySpec
- type EmbeddingProvider
- type EmbeddingRequest
- type EmbeddingResponse
- type Factory
- type FactoryRegistry
- type FlatPricing
- type HTTPServiceDefaults
- type HTTPServiceFields
- type HTTPServiceOption
- type ImageProvider
- type ImageRequest
- type ImageResponse
- type Implementation
- func (i *Implementation) Close() error
- func (i *Implementation) HealthCheck(ctx context.Context) error
- func (i *Implementation) Init(ctx context.Context) error
- func (i *Implementation) Name() string
- func (i *Implementation) Pricing() *PricingDescriptor
- func (i *Implementation) SetPricing(p *PricingDescriptor)
- func (i *Implementation) Type() ProviderType
- func (i *Implementation) Validate() error
- type InferenceProvider
- type InlinePricingResolver
- type LineItem
- type PriceItem
- type PricingDescriptor
- type PricingRef
- type PricingResolver
- type PricingSource
- type Provider
- type ProviderType
- type Registry
- func (r *Registry) CloseAll() error
- func (r *Registry) Get(name string, typ ProviderType) (Provider, error)
- func (r *Registry) GetAll(typ ProviderType) []Provider
- func (r *Registry) InitAll(ctx context.Context) error
- func (r *Registry) PricingResolver() PricingResolver
- func (r *Registry) Register(p Provider) error
- func (r *Registry) SetPricingResolver(res PricingResolver)
- type STTProvider
- type STTRequest
- type STTResponse
- type SpanArgs
- type TTSProvider
- type TTSRequest
- type TTSStream
- type TokenUsage
- type VideoProvider
- type VideoRequest
- type VideoResponse
Constants ¶
const ( UnitInputToken = "input_token" // full-price, uncached input UnitCacheReadToken = "cache_read_token" // prompt-cache read (discounted input) UnitCacheWriteToken = "cache_write_token" //nolint:gosec // prompt-cache creation (premium input), not a credential UnitOutputToken = "output_token" // visible output only, EXCLUDES reasoning UnitReasoningToken = "reasoning_token" // thinking tokens, priced additively UnitAudioInputToken = "audio_input_token" //nolint:gosec // realtime audio in, not a credential UnitAudioOutputToken = "audio_output_token" // realtime audio out )
Canonical token units. Providers MUST emit these names; pricing tables MUST price them by the same names.
Variables ¶
This section is empty.
Functions ¶
func APIKeyFromCredential ¶
func APIKeyFromCredential(c credentials.Credential) string
APIKeyFromCredential returns the raw API key from an APIKey credential, or "" for any other credential shape (or nil).
func AggregateCost ¶ added in v1.5.5
AggregateCost merges per-message CostInfo into one roll-up: it sums Quantities, merges Breakdown line items by (provider, capability, unit, dimensions), and re-derives the flat directional headlines so the TotalCost == Input+Output+Cached invariant holds on the aggregate. This is the single source of truth for cost roll-up — no caller sums CostInfo by hand.
A part with an empty Breakdown (headline-only: pre-migration provider results, or older/serialized CostInfo values that never populated Breakdown/Quantities) is never dropped — its flat fields are synthesized into breakdown lines so the cost flows through the same merge path. A part with a non-empty Breakdown uses only that Breakdown (its flat fields are re-derived output, not re-read) to avoid double-counting.
func CostInfoToMetaMap ¶
CostInfoToMetaMap serializes a CostInfo into the map[string]any shape the arena statestore expects when reading ancillary cost from Message.Meta keys (tts_cost, stt_cost, etc.). The keys and types must match what PromptArena's statestore telemetry costInfoFromMeta reads.
func GetTyped ¶
func GetTyped[T Provider](r *Registry, name string, typ ProviderType) (T, error)
GetTyped is a generic helper that returns a provider as a specific interface type T. Returns an error if the registered provider doesn't satisfy T.
func MakeCostInfo ¶
func MakeCostInfo( desc *PricingDescriptor, providerName string, capability ProviderType, quantities map[string]float64, latency time.Duration, ) *types.CostInfo
MakeCostInfo builds a *types.CostInfo from raw quantities and prices every unit it can match against the supplied descriptor. Returns the CostInfo with quantities and identity tags populated even if pricing is nil — callers can decide whether to drop a nil-cost entry. Any nonzero quantity unit that has no matching price item is NOT silently swallowed to $0: the priced-partial total is kept and the gap is surfaced via a deduped warning (see warnUnpriced), so operators see undercounted cost instead of a false zero. This is the shared cost-construction path for ancillary providers (TTS, STT, image gen) that report a single-quantity unit at call time.
func NewHTTPService ¶
func NewHTTPService( apiKey string, defaults HTTPServiceDefaults, opts ...HTTPServiceOption, ) (*Implementation, *HTTPServiceFields)
NewHTTPService produces the standard *Implementation + *HTTPServiceFields pair every HTTP-backed provider impl embeds, applying any caller-supplied HTTPServiceOption mutations on the way out. Eliminates per-impl constructor boilerplate.
func PriceUsage ¶ added in v1.5.5
func PriceUsage( desc *PricingDescriptor, providerName string, capability ProviderType, usage TokenUsage, dims map[string]string, latency time.Duration, ) types.CostInfo
PriceUsage prices a normalized TokenUsage against desc, populating the authoritative Quantities+Breakdown and deriving the flat headline view. A nonzero unit with no price (and a non-nil descriptor) is surfaced loudly (deduped) and contributes to no cost — the total is the priced-partial sum, never a fabricated constant and never a swallowed $0. A nil descriptor is a free/local provider: zero cost, no warning.
func ReadAllAudio ¶
ReadAllAudio drains a TTSStream into a byte slice and returns it along with the total cost. Convenience for callers that need the full audio up front (tests, batch synthesis, mocks).
func ResolveCredential ¶
func ResolveCredential( ctx context.Context, providerType string, cfgDir string, cred *credentials.CredentialConfig, ) (credentials.Credential, error)
ResolveCredential resolves a provider's credential block into a concrete Credential. Shared by every typed-provider package's factory layer.
Types ¶
type CapabilitySpec ¶
type CapabilitySpec struct {
// ID is a stable identifier; informational only at this layer.
ID string
// Type selects the implementation (e.g. openai, elevenlabs, cartesia).
Type string
// Model overrides the provider's default model.
Model string
// BaseURL overrides the provider's default API endpoint.
BaseURL string
// Credential carries the resolved credential.
Credential credentials.Credential
// AdditionalConfig carries provider-specific extras. Unknown keys
// are ignored.
AdditionalConfig map[string]any
}
CapabilitySpec is the unified runtime form of a typed-provider declaration (TTS, STT, embedding, image gen). The SDK's runtime-config layer translates pkg/config provider configs into this struct after resolving credentials.
Each capability package (tts, stt, embedding, image) aliases this type to preserve back-compat field-naming while sharing the factory machinery.
type EmbeddingProvider ¶
type EmbeddingProvider interface {
Provider
Embed(ctx context.Context, req EmbeddingRequest) (EmbeddingResponse, error)
}
EmbeddingProvider returns vectors for input texts.
type EmbeddingRequest ¶
EmbeddingRequest carries text inputs for a vector embedding call.
type EmbeddingResponse ¶
EmbeddingResponse holds the embedding vectors and metadata from a provider.
type Factory ¶
type Factory[T any] func(spec CapabilitySpec) (T, error)
Factory builds a typed Provider from a CapabilitySpec.
type FactoryRegistry ¶
type FactoryRegistry[T any] struct { // contains filtered or unexported fields }
FactoryRegistry is a typed registry keyed by the implementation discriminator (spec.Type). Each capability package owns one registry instance.
func NewFactoryRegistry ¶
func NewFactoryRegistry[T any]() *FactoryRegistry[T]
NewFactoryRegistry creates an empty registry.
func (*FactoryRegistry[T]) Create ¶
func (r *FactoryRegistry[T]) Create(spec CapabilitySpec) (T, error)
Create dispatches to the registered factory for spec.Type.
func (*FactoryRegistry[T]) Register ¶
func (r *FactoryRegistry[T]) Register(implType string, f Factory[T])
Register adds a factory under the given implementation type.
type FlatPricing ¶ added in v1.5.5
type FlatPricing struct {
Input float64 // per 1K input tokens
Output float64 // per 1K output tokens
}
FlatPricing is the legacy per-1K input/output rate a config may carry. It is mapped to canonical input_token/output_token price items when no richer descriptor is supplied. base defines its own type (rather than reusing a providers-package type) to avoid importing the providers package, which would create an import cycle.
type HTTPServiceDefaults ¶
type HTTPServiceDefaults struct {
// Name is the provider's unique registry name (e.g. "openai-whisper").
Name string
// Type is the capability discriminator (inference, tts, stt, ...).
Type ProviderType
// Pricing is the compiled-in pricing descriptor.
Pricing *PricingDescriptor
// BaseURL is the default API endpoint.
BaseURL string
// Model is the default model identifier.
Model string
// Timeout is the default HTTP client timeout. Zero is treated as
// http.DefaultClient (no timeout) — pass a positive value.
Timeout time.Duration
}
HTTPServiceDefaults carries the construction-time defaults for an HTTP service provider (TTS, STT impls). Used by NewHTTPService to produce the standard *Implementation + *HTTPServiceFields pair every impl embeds.
type HTTPServiceFields ¶
HTTPServiceFields is the shared HTTP-call configuration embedded by service-style providers (TTS, STT impls). Each impl embeds *HTTPServiceFields to inherit APIKey/BaseURL/Model/Client storage plus the With* option helpers in this package — eliminating per-package With* boilerplate.
type HTTPServiceOption ¶
type HTTPServiceOption func(*HTTPServiceFields)
HTTPServiceOption mutates an HTTPServiceFields. Each impl re-types this for their own option signatures (e.g., type OpenAIOption = HTTPServiceOption).
func WithAPIKey ¶
func WithAPIKey(k string) HTTPServiceOption
WithAPIKey sets the API key (rarely used directly; constructors take it as a positional arg, but exposed for completeness).
func WithBaseURL ¶
func WithBaseURL(url string) HTTPServiceOption
WithBaseURL overrides the service's API base URL (testing, proxies).
func WithClient ¶
func WithClient(c *http.Client) HTTPServiceOption
WithClient overrides the HTTP client (custom timeout / transport).
type ImageProvider ¶
type ImageProvider interface {
Provider
Generate(ctx context.Context, req ImageRequest) (ImageResponse, error)
}
ImageProvider generates images from prompts.
type ImageRequest ¶
type ImageRequest struct {
Prompt string
Size string // e.g. "1024x1024"
Quality string // e.g. "standard" | "hd"
Count int // default 1
Hints map[string]string
}
ImageRequest carries parameters for an image generation call.
type ImageResponse ¶
type ImageResponse struct {
Images [][]byte
MIMEType string
Cost *types.CostInfo
Latency time.Duration
}
ImageResponse holds generated image bytes and metadata from a provider.
type Implementation ¶
type Implementation struct {
// contains filtered or unexported fields
}
Implementation is an embeddable struct that supplies default Provider method implementations for a provider. Concrete impls populate the fields in their constructor and override any methods (Validate, Init, HealthCheck, Close) that need real behavior.
func NewImplementation ¶
func NewImplementation(name string, typ ProviderType, pricing *PricingDescriptor) *Implementation
NewImplementation constructs a helper. Pass nil pricing for free / local providers.
func (*Implementation) Close ¶
func (i *Implementation) Close() error
Close releases resources. Default no-op.
func (*Implementation) HealthCheck ¶
func (i *Implementation) HealthCheck(ctx context.Context) error
HealthCheck reports liveness. Default no-op.
func (*Implementation) Init ¶
func (i *Implementation) Init(ctx context.Context) error
Init performs asynchronous setup (network, warm-up). Default no-op.
func (*Implementation) Name ¶
func (i *Implementation) Name() string
Name returns the provider's unique registry name.
func (*Implementation) Pricing ¶
func (i *Implementation) Pricing() *PricingDescriptor
Pricing returns the configured pricing descriptor (may be nil). Safe to call on a nil receiver — a provider struct built via a raw literal (common in tests) that skips NewImplementation has a nil *Implementation, and this must degrade to "no pricing configured" rather than panic.
func (*Implementation) SetPricing ¶
func (i *Implementation) SetPricing(p *PricingDescriptor)
SetPricing allows post-construction pricing wiring (used when the resolver fills in pricing after Init completes).
func (*Implementation) Type ¶
func (i *Implementation) Type() ProviderType
Type returns the capability type.
func (*Implementation) Validate ¶
func (i *Implementation) Validate() error
Validate performs synchronous config validation. Default no-op.
type InferenceProvider ¶
type InferenceProvider interface {
Provider
}
InferenceProvider is the shared interface for chat / realtime / multimodal LLM providers. The full surface (Predict, PredictStream, etc.) is defined in runtime/providers/provider.go and embedded here via the existing providers.Provider interface, kept intact for back-compat.
For PR 1 this interface is forward-declared. Existing implementations satisfy it once they compose the base.Implementation helper (Task 7).
type InlinePricingResolver ¶
type InlinePricingResolver struct {
// contains filtered or unexported fields
}
InlinePricingResolver returns descriptors registered at construction time (typically by the config loader). Lookup is keyed by (impl, model, capability).
func NewInlinePricingResolver ¶
func NewInlinePricingResolver() *InlinePricingResolver
NewInlinePricingResolver creates an empty resolver.
func (*InlinePricingResolver) Register ¶
func (r *InlinePricingResolver) Register(ref PricingRef, desc *PricingDescriptor)
Register stores a pricing descriptor under the given reference.
func (*InlinePricingResolver) Resolve ¶
func (r *InlinePricingResolver) Resolve(ctx context.Context, ref PricingRef) (*PricingDescriptor, error)
Resolve returns the registered descriptor for ref, or an error if none.
type LineItem ¶
type LineItem struct {
Unit string `json:"unit"`
Quantity float64 `json:"quantity"`
Rate float64 `json:"rate"`
USD float64 `json:"usd"`
Dimensions map[string]string `json:"dimensions,omitempty"`
}
LineItem is one row of a cost breakdown for reports.
func ComputeCost ¶
func ComputeCost(desc *PricingDescriptor, info *types.CostInfo) (totalUSD float64, breakdown []LineItem, err error)
ComputeCost multiplies raw quantities by matching rates from the pricing descriptor. Returns total USD, the breakdown, and an error if ANY nonzero unit lacks a match (back-compat: callers relying on the strict error).
nil pricing returns zero cost without error (free / local provider).
type PriceItem ¶
type PriceItem struct {
Unit string `json:"unit"`
Rate float64 `json:"rate"`
Dimensions map[string]string `json:"dimensions,omitempty"`
}
PriceItem is one line of a pricing table: a rate per unit, optionally scoped by dimensions (e.g. image size + quality).
func (*PriceItem) UnmarshalJSON ¶
UnmarshalJSON normalizes the per-1M alias form into the canonical PriceItem shape.
type PricingDescriptor ¶
type PricingDescriptor struct {
Source PricingSource `json:"source"`
PricingCorrectAt time.Time `json:"correct_at,omitempty"`
Currency string `json:"currency,omitempty"` // default "usd"
Items []PriceItem `json:"items"`
}
PricingDescriptor is the runtime-resolved pricing for a single provider+capability.
func PricingFromAdditionalConfig ¶
func PricingFromAdditionalConfig(additional map[string]any) *PricingDescriptor
PricingFromAdditionalConfig extracts a *PricingDescriptor from a provider spec's AdditionalConfig map (under the "pricing" key) by JSON-round-tripping the value into the typed descriptor. Returns nil when the key is absent or the value can't be coerced — callers fall back to package-level defaults.
Used by the TTS and STT factories that translate pkg/config provider specs into runtime services.
func ResolveLLMPricing ¶ added in v1.5.5
func ResolveLLMPricing( configDesc *PricingDescriptor, flat FlatPricing, table map[string]*PricingDescriptor, model string, ) *PricingDescriptor
ResolveLLMPricing selects the pricing descriptor for a model, in order: explicit config descriptor > flat config pricing > embedded default table > nil (paid provider; PriceUsage will warn on nonzero unpriced units).
type PricingRef ¶
type PricingRef struct {
Impl string
Model string
Capability ProviderType
Hints map[string]string
}
PricingRef identifies what we're pricing — the resolver maps this to a PricingDescriptor.
type PricingResolver ¶
type PricingResolver interface {
Resolve(ctx context.Context, ref PricingRef) (*PricingDescriptor, error)
}
PricingResolver returns a PricingDescriptor for a given reference. Foundation PR ships only InlinePricingResolver; future work may add a remote impl that calls out to a service.
type PricingSource ¶
type PricingSource string
PricingSource discriminates how pricing values are obtained.
const ( // PricingSourceInline reads pricing from the loaded YAML descriptor. PricingSourceInline PricingSource = "inline" // PricingSourceRemote is reserved; see RemotePricingResolver (future work). PricingSourceRemote PricingSource = "remote" )
type Provider ¶
type Provider interface {
Name() string
Type() ProviderType
Pricing() *PricingDescriptor
Validate() error
Init(ctx context.Context) error
HealthCheck(ctx context.Context) error
Close() error
}
Provider is implemented by every provider type. It carries only the cross-cutting surface that the registry, config loader, metric collector, and cost rollup need.
type ProviderType ¶
type ProviderType string
ProviderType discriminates capability types. Used as a registry key, metric label, and span attribute.
const ( ProviderTypeInference ProviderType = "inference" ProviderTypeTTS ProviderType = "tts" ProviderTypeSTT ProviderType = "stt" ProviderTypeEmbedding ProviderType = "embedding" ProviderTypeImage ProviderType = "image" ProviderTypeVideo ProviderType = "video" )
Defined ProviderType values. New types should be added here and to AllProviderTypes.
func AllProviderTypes ¶
func AllProviderTypes() []ProviderType
AllProviderTypes returns every defined ProviderType. Used by the metric collector to pre-register ancillary metric families.
func ParseProviderType ¶
func ParseProviderType(s string) (ProviderType, error)
ParseProviderType validates and returns a ProviderType from a string.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry stores providers keyed by (name, capability).
func NewRegistry ¶
func NewRegistry() *Registry
NewRegistry creates an empty registry with an InlinePricingResolver.
func (*Registry) CloseAll ¶
CloseAll calls Close on every registered provider, returning the first error encountered.
func (*Registry) Get ¶
func (r *Registry) Get(name string, typ ProviderType) (Provider, error)
Get returns the provider registered under (name, capability), or an error.
func (*Registry) GetAll ¶
func (r *Registry) GetAll(typ ProviderType) []Provider
GetAll returns every provider of the given capability.
func (*Registry) PricingResolver ¶
func (r *Registry) PricingResolver() PricingResolver
PricingResolver returns the registry's resolver (used by provider constructors at registration time).
func (*Registry) Register ¶
Register adds a provider. Returns an error if (name, capability) is already registered.
func (*Registry) SetPricingResolver ¶
func (r *Registry) SetPricingResolver(res PricingResolver)
SetPricingResolver injects a non-default resolver (used by tests / future remote impl).
type STTProvider ¶
type STTProvider interface {
Provider
Transcribe(ctx context.Context, req STTRequest) (STTResponse, error)
}
STTProvider transcribes audio to text.
type STTRequest ¶
STTRequest carries audio input for a speech-to-text transcription call.
type STTResponse ¶
STTResponse holds the transcribed text and metadata from an STT provider.
type SpanArgs ¶
type SpanArgs struct {
Capability ProviderType
Operation string // "predict" | "synthesize" | "transcribe" | "embed" | "generate"
Provider string // base.Provider.Name()
Impl string // implementation discriminator (e.g. "openai", "imagen")
Model string
}
SpanArgs carries the standard attributes for a capability-scoped provider span.
type TTSProvider ¶
type TTSProvider interface {
Provider
SynthesizeTTS(ctx context.Context, req TTSRequest) (TTSStream, error)
}
TTSProvider produces audio from text. Streaming-first: every TTS call returns a TTSStream regardless of whether the underlying provider supports incremental synthesis. Buffered consumers can use ReadAllAudio to collect all chunks into a []byte.
The method is named SynthesizeTTS rather than Synthesize to avoid a naming conflict with the legacy tts.Service.Synthesize method that takes (text string, config SynthesisConfig). Both interfaces can be satisfied by the same concrete type simultaneously.
type TTSRequest ¶
type TTSRequest struct {
Text string
Voice string
Speed float32
Format string // audio format hint, e.g. "mp3", "pcm" (provider-specific)
SampleRate int // desired output sample rate in Hz (0 = provider default)
Hints map[string]string // additional dimension hints passed to pricing
}
TTSRequest carries parameters for a text-to-speech synthesis call.
type TTSStream ¶
type TTSStream interface {
// Chunks returns the channel of audio chunks. Caller must drain to
// completion or call Close to release resources. The channel closes
// when synthesis completes successfully or on error.
Chunks() <-chan audio.Chunk
// Cost returns the total cost of this synthesis. Returns nil before
// the chunk channel has closed; returns a populated *types.CostInfo
// afterwards. Pricing comes from the provider's PricingDescriptor.
Cost() *types.CostInfo
// Close cancels an in-progress stream and releases resources.
// Safe to call multiple times.
Close() error
}
TTSStream is the streaming output of a TTS provider's Synthesize call. It exposes the chunk channel that downstream pipeline stages consume, plus a typed accessor for the total cost (available once the chunk channel closes) and a Close method for early cancellation.
type TokenUsage ¶ added in v1.5.5
type TokenUsage struct {
Input int // full-price uncached input
CacheRead int
CacheWrite int
Output int // visible output only
Reasoning int
AudioInput int
AudioOutput int
// Extra carries future/uncommon units keyed by canonical unit name.
Extra map[string]float64
}
TokenUsage is the normalized, provider-agnostic usage a provider hands to PriceUsage. Each provider maps its wire usage into these canonical meanings, absorbing its own quirks (cache-inclusive vs -exclusive input, reasoning bundled into output vs separate) so every field means the same thing here.
func (TokenUsage) Quantities ¶ added in v1.5.5
func (u TokenUsage) Quantities() map[string]float64
Quantities converts the usage into the unit-keyed map the pricing engine consumes, omitting zero-valued units.
type VideoProvider ¶ added in v1.5.1
type VideoProvider interface {
Provider
Generate(ctx context.Context, req VideoRequest) (VideoResponse, error)
}
VideoProvider generates videos from prompts. No concrete provider implements this interface yet; it defines the shape that the video__generate tool resolves against once a provider (e.g. Veo) lands.