pricing

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jun 2, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package pricing is the domain layer for the Pricing entity — a named rate sheet owned by a Host and applied to one or more Models. One Pricing row holds every rate that bills against a (model, host) pair: input, output, cache_read, cache_creation, reasoning, audio_*, and any context-tier variants.

Pricing is owner=host so that "Anthropic's price list" and "Bedrock's price list" are two distinct entities even when they cover overlapping Models. TargetModelIDs lets one rate sheet cover a whole tier (claude-4 family etc.) without duplicating rows.

store.go is the data-access layer for Pricing. TargetModelIDs live in the pricing_models junction (not JSONB), so Upsert fans out across pricings + pricing_models inside a single transaction. host_id is a real column, hydrated alongside the rest of the row on List.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Meter

type Meter string

Meter is the dimension a Rate prices. Closed set; new meters require a schema bump (intentional — billing surface area should grow deliberately).

const (
	MeterTokensInput               Meter = "tokens.input"
	MeterTokensOutput              Meter = "tokens.output"
	MeterTokensCacheRead           Meter = "tokens.cache_read"
	MeterTokensCacheCreation       Meter = "tokens.cache_creation"
	MeterTokensReasoning           Meter = "tokens.reasoning"
	MeterTokensAudioInput          Meter = "tokens.audio_input"
	MeterTokensAudioOutput         Meter = "tokens.audio_output"
	MeterTokensAcceptedPrediction  Meter = "tokens.accepted_prediction"
	MeterTokensRejectedPrediction  Meter = "tokens.rejected_prediction"
	MeterTokensServerToolUseInput  Meter = "tokens.server_tool_use_input"
	MeterTokensServerToolUseOutput Meter = "tokens.server_tool_use_output"
)

func MeterForUsageKey

func MeterForUsageKey(k string) (Meter, bool)

MeterForUsageKey maps a usage.Tokens key (as emitted by Adapter.ExtractTokens) to its corresponding pricing Meter. Returns the meter and true if known, or "" and false for unpriced keys.

type Pricing

type Pricing struct {
	Meta meta.Metadata `json:"metadata" yaml:"metadata"`
	Spec Spec          `json:"spec"     yaml:"spec"`
}

Pricing is a rate sheet. Owner.Kind must be OwnerHost; Owner.ID is the Host id.

func (*Pricing) Cost

func (p *Pricing) Cost(tokens usage.Tokens) float64

Cost computes the total cost (in Spec.Currency units, typically USD) for the given Tokens map. Tier selection uses the input token count — the conventional axis for context-length tiers across major providers. Keys not mapped by MeterForUsageKey are silently skipped (unpriced dimension). Returns 0 when Pricing is disabled or carries no rates.

func (*Pricing) IsEnabled

func (p *Pricing) IsEnabled() bool

IsEnabled returns true when Enabled is unset or explicitly true.

func (*Pricing) RateFor

func (p *Pricing) RateFor(meter Meter, tokens int) (*Rate, bool)

RateFor returns the rate that should bill against the given meter and request-side token count. Walks Rates for the meter and picks the row with the largest AboveTokens that is still ≤ tokens. Returns (nil, false) if no rate exists for the meter.

func (*Pricing) Validate

func (p *Pricing) Validate() error

Validate runs intra-row rules via the shared meta.Validator and enforces the Pricing-specific invariants:

  • Owner.Kind == OwnerHost and Owner.ID is set (the Host id).
  • No two Rates share the same (Meter, AboveTokens) — would be ambiguous at billing time.

Cross-entity checks (TargetModelIDs resolve, no two enabled Pricings claim the same (model, host) pair) live in the catalog composition layer.

type Rate

type Rate struct {
	Meter       Meter   `` /* 319-byte string literal not displayed */
	Unit        Unit    `json:"unit"                  yaml:"unit"                  validate:"required,oneof=per_million per_unit"`
	Amount      float64 `json:"amount"                yaml:"amount"                validate:"required,gt=0"`
	AboveTokens int     `json:"aboveTokens,omitempty" yaml:"aboveTokens,omitempty" validate:"gte=0"`
}

Rate is one priced meter. AboveTokens=0 is the base tier; AboveTokens>0 is the rate charged once the request's billable token count exceeds that threshold. The billing-time picker walks rates for the meter and applies the largest qualifying threshold.

type Spec

type Spec struct {
	Currency       string   `json:"currency"             yaml:"currency"             validate:"required"`
	TargetModelIDs []string `json:"targetModels"         yaml:"targetModels"         validate:"required,min=1,dive,required"`
	Rates          []Rate   `json:"rates"                yaml:"rates"                validate:"required,min=1,dive"`
	Enabled        *bool    `json:"enabled,omitempty"    yaml:"enabled,omitempty"`
}

Spec carries the rate list, the target model set, currency, and an enable flag.

type Store

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

Store is the Pricing data-access type. Holds a pool so Upsert can run a multi-table transaction.

func NewStore

func NewStore(pool *pgxpool.Pool) *Store

NewStore constructs a Store bound to a pool.

func (*Store) Delete

func (s *Store) Delete(ctx context.Context, id string) error

Delete removes a Pricing by id. Junction rows cascade via FK.

func (*Store) Get

func (s *Store) Get(ctx context.Context, id string) (*Pricing, error)

Get returns the Pricing with the given id, hydrating TargetModelIDs. Returns (nil, nil) if not found.

func (*Store) List

func (s *Store) List(ctx context.Context) ([]*Pricing, error)

List returns every Pricing row with Spec.TargetModelIDs hydrated from the pricing_models junction in declaration order.

func (*Store) Upsert

func (s *Store) Upsert(ctx context.Context, p *Pricing) error

Upsert writes p across pricings + pricing_models in a single tx. Caller stamps Meta.ID and Owner.ID (host id).

type Unit

type Unit string

Unit is how Amount is interpreted. per_million is the common case for token rates (Amount=2.50 means $2.50 per 1M tokens). per_unit is for future meters like per-image or per-call.

const (
	UnitPerMillion Unit = "per_million"
	UnitPerUnit    Unit = "per_unit"
)

Jump to

Keyboard shortcuts

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