manifest

package
v0.4.2 Latest Latest
Warning

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

Go to latest
Published: Jun 28, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package wire handles conversion between the operator-facing YAML/JSON wire format and the domain structs in the app/* entity packages.

Wire format uses entity *names* (DNS-1123 slugs) for cross-references. Domain structs use *ids* (UUIDv7). This package bridges the gap.

Typical flow:

  1. Parse raw YAML via Parse or LoadDir → []Document
  2. Build a Resolver from your name→id index (snapshot, seed index, etc.)
  3. Call ToXxx(dto, resolver) → domain struct ready for Store.Upsert

Reverse direction (GET responses):

  1. Receive domain struct from store
  2. Build a ReverseResolver from your id→name index
  3. Call FromXxx(domain, rev) → wire DTO suitable for JSON/YAML output

Index

Constants

View Source
const APIVersion = "relay.wyolet.dev/v1alpha2"

APIVersion is the catalog schema version every relay-aware YAML must declare. v1alpha2 introduces Model.Spec.Snapshots + Pointer and the expanded pricing meter enum. Bumping is a wipe-and-reseed migration — the parser rejects mismatched versions outright.

Variables

This section is empty.

Functions

func ToHost

func ToHost(d HostDTO, idx Resolver) (*host.Host, error)

func ToHostBinding

func ToHostBinding(d HostBindingDTO, idx Resolver) (*binding.Binding, error)

ToHostBinding resolves model, host, and (optional) pricing names to ids.

func ToHostKey

func ToHostKey(d HostKeyDTO, idx Resolver) (*hostkey.HostKey, error)

ToHostKey resolves Spec.HostID and Spec.PolicyID (name → id).

func ToModel

func ToModel(d ModelDTO, idx Resolver) (*model.Model, error)

ToModel resolves the model's owning provider name to an id.

Provider owner: the wire form stores the provider *name* in Metadata.Owner.ID when coming from YAML. Callers who need name→id resolution for the owner should do so before this call, or supply the provider id directly.

func ToPolicy

func ToPolicy(d PolicyDTO, idx Resolver) (*policy.Policy, error)

func ToPricing

func ToPricing(d PricingDTO, idx Resolver) (*pricing.Pricing, error)

ToPricing resolves the owner host name → id and target model names → ids.

func ToProvider

func ToProvider(d ProviderDTO, _ Resolver) (*provider.Provider, error)

func ToRateLimit

func ToRateLimit(d RateLimitDTO, idx Resolver) (*ratelimit.RateLimit, error)

ToRateLimit converts a RateLimitDTO to a domain RateLimit. Resolves owner.id from a host *name* to its id when Owner.Kind=host (the wire form uses names for human readability).

func ToRelayKey

func ToRelayKey(d RelayKeyDTO, idx Resolver) (*relaykey.RelayKey, error)

Types

type Document

type Document struct {
	Provider    *ProviderDTO
	Host        *HostDTO
	Model       *ModelDTO
	HostKey     *HostKeyDTO
	Policy      *PolicyDTO
	RateLimit   *RateLimitDTO
	RelayKey    *RelayKeyDTO
	Pricing     *PricingDTO
	HostBinding *HostBindingDTO
	Setting     *SettingDTO
}

Document is a discriminated union over all supported wire kinds. Exactly one of the fields below is non-nil after successful parsing.

func LoadDir

func LoadDir(dir string) ([]Document, error)

LoadDir walks dir for .yaml / .yml files and parses each. Documents from all files are merged into a single slice. File order is deterministic (lexicographic).

Any directory named "drafts" at any depth is skipped, as is any file matching "*.draft.yaml" / "*.draft.yml". The catalog uses these to gate resources that have been imported but not yet curated (e.g. unverified baseURL/adapter). Promote by moving the subtree out of drafts/ or by dropping the .draft suffix.

func Parse

func Parse(r io.Reader) ([]Document, error)

Parse reads one or more YAML documents from r and returns a Document slice. Multi-doc YAML (--- separated) is fully supported.

func (Document) Kind

func (d Document) Kind() string

Kind returns the kind string of the contained document.

type HostBindingDTO

type HostBindingDTO struct {
	APIVersion string          `json:"apiVersion" yaml:"apiVersion"`
	Kind       string          `json:"kind"       yaml:"kind"`
	Metadata   WireMeta        `json:"metadata"   yaml:"metadata"`
	Spec       HostBindingSpec `json:"spec"       yaml:"spec"`
}

HostBindingDTO is the top-level wire form of a standalone HostBinding entity. Model and Host carry *names* (wire form); translate resolves them to ids.

func FromHostBinding

func FromHostBinding(b *binding.Binding, rev ReverseResolver) HostBindingDTO

type HostBindingSpec

type HostBindingSpec struct {
	// Model is the model *name* (wire form).
	Model string `json:"model" yaml:"model"`
	// Host is the host *name* (wire form).
	Host         string `json:"host"                   yaml:"host"`
	Adapter      string `json:"adapter"                yaml:"adapter"`
	UpstreamName string `json:"upstreamName,omitempty" yaml:"upstreamName,omitempty"`
	// Pricing is an optional pricing *name* (wire form).
	Pricing   string   `json:"pricing,omitempty"  yaml:"pricing,omitempty"`
	Enabled   *bool    `json:"enabled,omitempty"  yaml:"enabled,omitempty"`
	Snapshots []string `json:"snapshots,omitempty" yaml:"snapshots,omitempty"`
}

HostBindingSpec is the spec block of a standalone HostBinding.

type HostDTO

type HostDTO struct {
	APIVersion string   `json:"apiVersion" yaml:"apiVersion"`
	Kind       string   `json:"kind"       yaml:"kind"`
	Metadata   WireMeta `json:"metadata"   yaml:"metadata"`
	Spec       HostSpec `json:"spec"       yaml:"spec"`
}

HostDTO is the wire form of a Host.

func FromHost

func FromHost(h *host.Host, rev ReverseResolver) HostDTO

type HostKeyDTO

type HostKeyDTO struct {
	APIVersion string      `json:"apiVersion" yaml:"apiVersion"`
	Kind       string      `json:"kind"       yaml:"kind"`
	Metadata   WireMeta    `json:"metadata"   yaml:"metadata"`
	Spec       HostKeySpec `json:"spec"       yaml:"spec"`
}

HostKeyDTO is the wire form of a HostKey. Spec.HostID is a host *name* here.

func FromHostKey

func FromHostKey(k *hostkey.HostKey, rev ReverseResolver) HostKeyDTO

type HostKeySpec

type HostKeySpec struct {
	// HostID and PolicyID carry *names* on the wire; translate resolves
	// to ids when producing the domain shape.
	HostID      string           `json:"hostId"                yaml:"hostId"`
	PolicyID    string           `json:"policyId"              yaml:"policyId"`
	ValueFrom   HostKeyValueFrom `json:"valueFrom"             yaml:"valueFrom"`
	DefaultTier string           `json:"defaultTier,omitempty" yaml:"defaultTier,omitempty"`
	// PricingStrategy is the billing mode this credential is (api | sub).
	// Empty defaults to "api". Must be one of the host's pricingStrategies.
	PricingStrategy string `json:"pricingStrategy,omitempty" yaml:"pricingStrategy,omitempty"`
	Enabled         *bool  `json:"enabled,omitempty"     yaml:"enabled,omitempty"`
	Value           string `json:"-"                     yaml:"value,omitempty"`
}

type HostKeyValueFrom

type HostKeyValueFrom struct {
	Kind     string `json:"kind"               yaml:"kind"`
	Env      string `json:"env,omitempty"      yaml:"env,omitempty"`
	Provider string `json:"provider,omitempty" yaml:"provider,omitempty"`
}

type HostSpec

type HostSpec struct {
	BaseURL string            `json:"baseURL"               yaml:"baseURL"`
	Backend map[string]string `json:"backend,omitempty"     yaml:"backend,omitempty"`
	// Policies holds policy *names* (wire form), resolved to ids on parse.
	Policies []string `json:"policies,omitempty"    yaml:"policies,omitempty"`
	// DefaultPolicy is a policy *name* (wire form) referencing one of Policies.
	DefaultPolicy string `json:"defaultPolicy,omitempty" yaml:"defaultPolicy,omitempty"`
	NoAuth        bool   `json:"noAuth,omitempty"      yaml:"noAuth,omitempty"`
	// PricingStrategies is the host's menu of offered billing modes
	// (api | sub). Empty defaults to ["api"].
	PricingStrategies []string   `json:"pricingStrategies,omitempty" yaml:"pricingStrategies,omitempty"`
	Enabled           *bool      `json:"enabled,omitempty"     yaml:"enabled,omitempty"`
	HomepageURL       string     `json:"homepageURL,omitempty" yaml:"homepageURL,omitempty"`
	DocsURL           string     `json:"docsURL,omitempty"     yaml:"docsURL,omitempty"`
	ConsoleURL        string     `json:"consoleURL,omitempty"  yaml:"consoleURL,omitempty"`
	StatusPageURL     string     `json:"statusPageURL,omitempty" yaml:"statusPageURL,omitempty"`
	Icon              *meta.Icon `json:"icon,omitempty"        yaml:"icon,omitempty"`
}

type MapResolver

type MapResolver struct {
	Providers  map[string]string
	Hosts      map[string]string
	Policies   map[string]string
	Models     map[string]string
	HostKeys   map[string]string
	RateLimits map[string]string
	Pricings   map[string]string
	Bindings   map[string]string
}

MapResolver is a convenience implementation of Resolver backed by plain maps. Useful in tests and seed tooling.

func (MapResolver) BindingID

func (m MapResolver) BindingID(name string) (string, bool)

func (MapResolver) HostID

func (m MapResolver) HostID(name string) (string, bool)

func (MapResolver) HostKeyID

func (m MapResolver) HostKeyID(name string) (string, bool)

func (MapResolver) ModelID

func (m MapResolver) ModelID(name string) (string, bool)

func (MapResolver) PolicyID

func (m MapResolver) PolicyID(name string) (string, bool)

func (MapResolver) PricingID

func (m MapResolver) PricingID(name string) (string, bool)

func (MapResolver) ProviderID

func (m MapResolver) ProviderID(name string) (string, bool)

func (MapResolver) RateLimitID

func (m MapResolver) RateLimitID(name string) (string, bool)

type MapReverseResolver

type MapReverseResolver struct {
	Providers  map[string]string
	Hosts      map[string]string
	Policies   map[string]string
	Models     map[string]string
	HostKeys   map[string]string
	RateLimits map[string]string
	Pricings   map[string]string
	Bindings   map[string]string
}

MapReverseResolver is a convenience implementation of ReverseResolver backed by plain maps.

func (MapReverseResolver) BindingName

func (m MapReverseResolver) BindingName(id string) (string, bool)

func (MapReverseResolver) HostKeyName

func (m MapReverseResolver) HostKeyName(id string) (string, bool)

func (MapReverseResolver) HostName

func (m MapReverseResolver) HostName(id string) (string, bool)

func (MapReverseResolver) ModelName

func (m MapReverseResolver) ModelName(id string) (string, bool)

func (MapReverseResolver) PolicyName

func (m MapReverseResolver) PolicyName(id string) (string, bool)

func (MapReverseResolver) PricingName

func (m MapReverseResolver) PricingName(id string) (string, bool)

func (MapReverseResolver) ProviderName

func (m MapReverseResolver) ProviderName(id string) (string, bool)

func (MapReverseResolver) RateLimitName

func (m MapReverseResolver) RateLimitName(id string) (string, bool)

type ModelDTO

type ModelDTO struct {
	APIVersion string    `json:"apiVersion" yaml:"apiVersion"`
	Kind       string    `json:"kind"       yaml:"kind"`
	Metadata   WireMeta  `json:"metadata"   yaml:"metadata"`
	Spec       ModelSpec `json:"spec"       yaml:"spec"`
}

ModelDTO is the wire form of a Model. Owner.ID in the wire form should be the provider *name*; translate resolves it.

func FromModel

func FromModel(m *model.Model, rev ReverseResolver) ModelDTO

type ModelSpec

type ModelSpec struct {
	Family  string `json:"family,omitempty"  yaml:"family,omitempty"`
	Version string `json:"version,omitempty" yaml:"version,omitempty"`

	Capabilities model.Capabilities `json:"capabilities,omitempty" yaml:"capabilities,omitempty"`
	Modalities   model.Modalities   `json:"modalities,omitempty"   yaml:"modalities,omitempty"`

	ContextWindowInput  int `json:"contextWindowInput,omitempty"  yaml:"contextWindowInput,omitempty"`
	ContextWindowOutput int `json:"contextWindowOutput,omitempty" yaml:"contextWindowOutput,omitempty"`
	ContextWindowTotal  int `json:"contextWindowTotal,omitempty"  yaml:"contextWindowTotal,omitempty"`
	MaxOutputTokens     int `json:"maxOutputTokens,omitempty"     yaml:"maxOutputTokens,omitempty"`

	KnowledgeCutoff string             `json:"knowledgeCutoff,omitempty" yaml:"knowledgeCutoff,omitempty"`
	ReleaseDate     string             `json:"releaseDate,omitempty"     yaml:"releaseDate,omitempty"`
	DeprecationDate string             `json:"deprecationDate,omitempty" yaml:"deprecationDate,omitempty"`
	Deprecation     *model.Deprecation `json:"deprecation,omitempty"     yaml:"deprecation,omitempty"`

	Tags                 []string `json:"tags,omitempty"                 yaml:"tags,omitempty"`
	Documentation        string   `json:"documentation,omitempty"        yaml:"documentation,omitempty"`
	License              string   `json:"license,omitempty"              yaml:"license,omitempty"`
	ProviderModelPageURL string   `json:"providerModelPageURL,omitempty" yaml:"providerModelPageURL,omitempty"`

	Enabled *bool `json:"enabled,omitempty" yaml:"enabled,omitempty"`

	Snapshots []model.Snapshot `json:"snapshots" yaml:"snapshots"`
	Pointer   string           `json:"pointer"   yaml:"pointer"`

	// Aliases are resolution-only matchers (see model.Spec.Aliases). Plain
	// strings, no cross-refs to resolve.
	Aliases []string `json:"aliases,omitempty" yaml:"aliases,omitempty"`
}

type PolicyDTO

type PolicyDTO struct {
	APIVersion string     `json:"apiVersion" yaml:"apiVersion"`
	Kind       string     `json:"kind"       yaml:"kind"`
	Metadata   WireMeta   `json:"metadata"   yaml:"metadata"`
	Spec       PolicySpec `json:"spec"       yaml:"spec"`
}

PolicyDTO carries policy-level model-handling flags + the grant list.

func FromPolicy

func FromPolicy(p *policy.Policy, rev ReverseResolver) PolicyDTO

type PolicySpec

type PolicySpec struct {
	// Models holds model *names* (wire form).
	Models []string `json:"models,omitempty"    yaml:"models,omitempty"`
	// HostKeys holds host-key *names* (wire form).
	HostKeys []string `json:"hostKeys,omitempty"  yaml:"hostKeys,omitempty"`

	// RateLimit holds a rate-limit *name* (wire form). Mutually exclusive
	// with RLBindings.
	RateLimit string `json:"rateLimit,omitempty" yaml:"rateLimit,omitempty"`

	// RLBindings is the per-model rate-limit map (wire form). Each entry's
	// RateLimit field carries a *name* that translate resolves to an id.
	RLBindings []RLBindingDTO `json:"rlBindings,omitempty" yaml:"rlBindings,omitempty"`

	KeySelection          string `json:"keySelection,omitempty"          yaml:"keySelection,omitempty"`
	SkipDefaultLimits     bool   `json:"skipDefaultLimits,omitempty"     yaml:"skipDefaultLimits,omitempty"`
	IncludeDeprecated     bool   `json:"includeDeprecated,omitempty"     yaml:"includeDeprecated,omitempty"`
	Enabled               *bool  `json:"enabled,omitempty"               yaml:"enabled,omitempty"`
	PayloadLoggingEnabled bool   `json:"payloadLoggingEnabled,omitempty" yaml:"payloadLoggingEnabled,omitempty"`
}

type PricingDTO

type PricingDTO struct {
	APIVersion string      `json:"apiVersion" yaml:"apiVersion"`
	Kind       string      `json:"kind"       yaml:"kind"`
	Metadata   WireMeta    `json:"metadata"   yaml:"metadata"`
	Spec       PricingSpec `json:"spec"       yaml:"spec"`
}

PricingDTO is the wire form of a Pricing. Owner.ID is a host *name* here. TargetModels holds model *names* (wire form).

func FromPricing

func FromPricing(p *pricing.Pricing, rev ReverseResolver) PricingDTO

type PricingRateDTO

type PricingRateDTO struct {
	Meter       string  `json:"meter"                 yaml:"meter"`
	Unit        string  `json:"unit"                  yaml:"unit"`
	Amount      float64 `json:"amount"                yaml:"amount"`
	AboveTokens int     `json:"aboveTokens,omitempty" yaml:"aboveTokens,omitempty"`
}

PricingRateDTO mirrors pricing.Rate using plain types.

type PricingSpec

type PricingSpec struct {
	Currency     string           `json:"currency"          yaml:"currency"`
	TargetModels []string         `json:"targetModels"      yaml:"targetModels"`
	Rates        []PricingRateDTO `json:"rates"             yaml:"rates"`
	Enabled      *bool            `json:"enabled,omitempty" yaml:"enabled,omitempty"`
}

type ProviderDTO

type ProviderDTO struct {
	APIVersion string       `json:"apiVersion" yaml:"apiVersion"`
	Kind       string       `json:"kind"       yaml:"kind"`
	Metadata   WireMeta     `json:"metadata"   yaml:"metadata"`
	Spec       ProviderSpec `json:"spec"      yaml:"spec"`
}

ProviderDTO is the wire form of a Provider. No cross-refs — Provider has only display fields in its spec.

type ProviderSpec

type ProviderSpec struct {
	Enabled       *bool      `json:"enabled,omitempty"       yaml:"enabled,omitempty"`
	HomepageURL   string     `json:"homepageURL,omitempty"   yaml:"homepageURL,omitempty"`
	DocsURL       string     `json:"docsURL,omitempty"       yaml:"docsURL,omitempty"`
	StatusPageURL string     `json:"statusPageURL,omitempty" yaml:"statusPageURL,omitempty"`
	Icon          *meta.Icon `json:"icon,omitempty"          yaml:"icon,omitempty"`
}

type RLBindingDTO

type RLBindingDTO struct {
	Models    []string `json:"models"    yaml:"models"`
	RateLimit string   `json:"rateLimit" yaml:"rateLimit"`
}

RLBindingDTO is the wire form of a policy.RLBinding. Models are modelref DSL strings carried verbatim; RateLimit is a name resolved to an id.

type RateLimitDTO

type RateLimitDTO struct {
	APIVersion string        `json:"apiVersion" yaml:"apiVersion"`
	Kind       string        `json:"kind"       yaml:"kind"`
	Metadata   WireMeta      `json:"metadata"   yaml:"metadata"`
	Spec       RateLimitSpec `json:"spec"      yaml:"spec"`
}

RateLimitDTO is the wire form of a RateLimit. No cross-refs.

type RateLimitRule

type RateLimitRule struct {
	Meter    string      `json:"meter"    yaml:"meter"`
	Amount   int64       `json:"amount"   yaml:"amount"`
	Window   interface{} `json:"window"   yaml:"window"` // string ("30s") or int64 ns
	Strategy string      `json:"strategy" yaml:"strategy"`
}

type RateLimitSpec

type RateLimitSpec struct {
	Rules   []RateLimitRule `json:"rules"             yaml:"rules"`
	Enabled *bool           `json:"enabled,omitempty" yaml:"enabled,omitempty"`
}

type RelayKeyDTO

type RelayKeyDTO struct {
	APIVersion string       `json:"apiVersion" yaml:"apiVersion"`
	Kind       string       `json:"kind"       yaml:"kind"`
	Metadata   WireMeta     `json:"metadata"   yaml:"metadata"`
	Spec       RelayKeySpec `json:"spec"       yaml:"spec"`
}

RelayKeyDTO is the wire form of a RelayKey. Policy is a name.

func FromRelayKey

func FromRelayKey(k *relaykey.RelayKey, rev ReverseResolver) RelayKeyDTO

type RelayKeySpec

type RelayKeySpec struct {
	// Policy is the policy *name* (wire form).
	Policy                string  `json:"policy"                      yaml:"policy"`
	KeyHash               string  `json:"keyHash"                     yaml:"keyHash"`
	Prefix                string  `json:"prefix,omitempty"            yaml:"prefix,omitempty"`
	RevokedAt             *string `json:"revokedAt,omitempty"         yaml:"revokedAt,omitempty"`
	Enabled               *bool   `json:"enabled,omitempty"           yaml:"enabled,omitempty"`
	PassthroughAllowed    bool    `json:"passthroughAllowed,omitempty" yaml:"passthroughAllowed,omitempty"`
	PayloadLoggingEnabled bool    `json:"payloadLoggingEnabled,omitempty" yaml:"payloadLoggingEnabled,omitempty"`
}

type Resolver

type Resolver interface {
	ProviderID(name string) (string, bool)
	HostID(name string) (string, bool)
	PolicyID(name string) (string, bool)
	ModelID(name string) (string, bool)
	HostKeyID(name string) (string, bool)
	RateLimitID(name string) (string, bool)
	PricingID(name string) (string, bool)
	BindingID(name string) (string, bool)
}

Resolver resolves entity names to ids. The caller builds one from their name→id index (a snapshot, a seed index built against live PG state, etc.). Wire needs only this narrow interface — it never touches a full catalog or storage layer.

type ReverseResolver

type ReverseResolver interface {
	ProviderName(id string) (string, bool)
	HostName(id string) (string, bool)
	PolicyName(id string) (string, bool)
	ModelName(id string) (string, bool)
	HostKeyName(id string) (string, bool)
	RateLimitName(id string) (string, bool)
	PricingName(id string) (string, bool)
	BindingName(id string) (string, bool)
}

ReverseResolver resolves entity ids to names. Used to render domain structs back to wire DTOs for admin GET responses.

type SettingDTO

type SettingDTO struct {
	APIVersion string    `json:"apiVersion" yaml:"apiVersion"`
	Kind       string    `json:"kind"       yaml:"kind"`
	Metadata   WireMeta  `json:"metadata"   yaml:"metadata"`
	Spec       yaml.Node `json:"-"          yaml:"spec"`
}

SettingDTO is the wire form of a settings section. Unlike the catalog kinds the spec shape is not fixed — it varies per section, with metadata.name selecting the registered settings.Section whose typed value the spec must match. The spec is therefore carried as a raw node and validated downstream by that section's Decode. Settings are singletons keyed by name, so the owner/id/label metadata fields are unused.

func (*SettingDTO) SpecJSON

func (d *SettingDTO) SpecJSON() (json.RawMessage, error)

SpecJSON renders the raw spec node as JSON for the settings store, which validates it against the section's typed value via the section's Decode.

type WireMeta

type WireMeta struct {
	ID          string            `json:"id,omitempty"          yaml:"id,omitempty"`
	Name        string            `json:"name"                  yaml:"name"`
	DisplayName string            `json:"displayName,omitempty" yaml:"displayName,omitempty"`
	Description string            `json:"description,omitempty" yaml:"description,omitempty"`
	Owner       WireOwner         `json:"owner,omitempty"       yaml:"owner,omitempty"`
	Labels      map[string]string `json:"labels,omitempty"      yaml:"labels,omitempty"`
}

WireMeta is the metadata block shared by all wire DTOs. ID is optional on create (server stamps a UUIDv7); required on update.

type WireOwner

type WireOwner struct {
	Kind meta.OwnerKind `json:"kind,omitempty" yaml:"kind,omitempty"`
	Name string         `json:"name,omitempty" yaml:"name,omitempty"`
	ID   string         `json:"id,omitempty"   yaml:"id,omitempty"`
}

WireOwner is the wire form of meta.Owner. The referenced row is named — translate functions resolve Name → id when producing the domain shape, and reverse-resolve id → Name when emitting the wire shape. ID is the id-form for API clients that already hold a UUID; either field is accepted on read, with ID taking precedence.

Jump to

Keyboard shortcuts

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