modelcontract

package
v0.16.2 Latest Latest
Warning

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

Go to latest
Published: Jun 3, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package modelcontract defines the canonical, provider-agnostic model schema and the adapter interface that normalizes each provider's native model API into it.

The goal is a single contract the rest of the application consumes with confidence: every model has the same shape with normalized capabilities, pricing, context window, and lifecycle, regardless of how the originating provider happens to report them. Provider quirks live ONLY inside adapters. Values that genuinely can't be determined are left explicitly unknown (nil pointers / empty slices), never silently approximated.

Index

Constants

View Source
const (
	RolePrimary  = "primary"
	RoleSubagent = "subagent"
)

Role names a model can be eligible/recommended for.

View Source
const (
	StatusActive     = "active"
	StatusDeprecated = "deprecated"
	StatusPreview    = "preview"
)

Lifecycle status values.

View Source
const (
	// SubagentMinContext is the hard floor: below this, no eligible roles.
	SubagentMinContext = 64_000
	// PrimaryMinContext is required for the primary role, and is also the
	// threshold at/above which no context warning is attached.
	PrimaryMinContext = 128_000
)

Agentic-coding context thresholds for sprout. A context window below SubagentMinContext is a hard block — sprout's agentic loops (tool results, file reads, repo context) need room to work, and below ~64K a model is not usable. Between SubagentMinContext and PrimaryMinContext a model is usable only in a pinch and carries a strong warning. Eligibility ≠ recommendation; the capability probe provides the authoritative agentic-capable signal.

View Source
const SchemaVersion = 2

SchemaVersion is the version of the canonical published file format. Bumped only for breaking changes; consumers should accept known versions.

Variables

This section is empty.

Functions

func Bool

func Bool(b bool) *bool

Bool returns a pointer to b, for setting tri-state capabilities.

func CapabilityTags

func CapabilityTags(c Capabilities) []string

CapabilityTags renders known-true capabilities as legacy tag strings, for consumers/wire formats that carry capabilities as a flat tag list.

func ClassifyEligibleRoles

func ClassifyEligibleRoles(m CanonicalModel) []string

ClassifyEligibleRoles returns the agentic roles a model meets the minimum deterministic bar for. A model that is *known* to lack tool calling is never eligible (tool use is mandatory for agentic coding); unknown tool support gets the benefit of the doubt at this pre-filter stage — the probe decides. Below SubagentMinContext (or unknown context) returns nil — a hard block.

func ContextWarning

func ContextWarning(contextWindow int) string

ContextWarning returns a strong, non-blocking warning when a model's context window is usable but below the recommended size for sprout (the SubagentMinContext–PrimaryMinContext band). It returns empty when the context is adequate (>= PrimaryMinContext) or when the model is hard-blocked (< SubagentMinContext, which yields no eligible roles instead of a warning).

func FillEligibleRoles

func FillEligibleRoles(models []CanonicalModel)

FillEligibleRoles populates EligibleRoles and any derived Warnings for every model from its canonical fields. Always recomputed (deterministic) so it stays consistent with the current thresholds/capabilities.

func IsKnownFalse

func IsKnownFalse(b *bool) bool

IsKnownFalse reports whether a tri-state capability is known-false (as opposed to unknown).

func IsTrue

func IsTrue(b *bool) bool

IsTrue reports whether a tri-state capability is known-true.

Types

type CanonicalModel

type CanonicalModel struct {
	// Identity
	ID          string `json:"id"`       // inference ID (provider-native)
	Provider    string `json:"provider"` // "deepinfra", "openrouter", …
	DisplayName string `json:"display_name,omitempty"`
	Description string `json:"description,omitempty"`

	// Limits — 0 means unknown (documented convention).
	ContextWindow   int `json:"context_window,omitempty"`
	MaxOutputTokens int `json:"max_output_tokens,omitempty"`

	// Pricing — nil means unknown (NOT free).
	Pricing *Pricing `json:"pricing,omitempty"`

	// Capabilities — each is tri-state (see Capabilities).
	Capabilities Capabilities `json:"capabilities"`

	// Modality, e.g. ["text","image"].
	InputModalities  []string `json:"input_modalities,omitempty"`
	OutputModalities []string `json:"output_modalities,omitempty"`

	// Lifecycle
	Status     string `json:"status,omitempty"` // StatusActive / StatusDeprecated / StatusPreview
	ReplacedBy string `json:"replaced_by,omitempty"`

	// Derived (not reported by the provider) — populated by sprout, not adapters.
	EligibleRoles    []string     `json:"eligible_roles,omitempty"`    // deterministic pre-filter
	Probe            *ProbeResult `json:"probe,omitempty"`             // capability probe (later phase)
	RecommendedRoles []string     `json:"recommended_roles,omitempty"` // post-probe (later phase)
	Warnings         []string     `json:"warnings,omitempty"`          // non-blocking caveats to surface (e.g. small context)

	// Provenance
	Source    string `json:"source,omitempty"`     // e.g. "deepinfra:/models/list"
	UpdatedAt string `json:"updated_at,omitempty"` // RFC3339
}

CanonicalModel is the normalized, provider-agnostic representation of a model.

func EnrichFromReference

func EnrichFromReference(dst, ref CanonicalModel) CanonicalModel

EnrichFromReference fills unknown fields on dst from a reference model that represents the same underlying model on another provider. Capabilities, context, and modality are copied with confidence (same model). Pricing is copied only when dst has none, and is marked Estimated because the originating provider's price may be account-specific.

type Capabilities

type Capabilities struct {
	Tools            *bool `json:"tools,omitempty"`
	Vision           *bool `json:"vision,omitempty"`
	Reasoning        *bool `json:"reasoning,omitempty"`
	StructuredOutput *bool `json:"structured_output,omitempty"`
	Streaming        *bool `json:"streaming,omitempty"`
}

Capabilities is a tri-state capability set: a non-nil *bool is a known true/false; nil means the provider's metadata didn't let us determine it. Consumers must treat nil as "unknown", never as false.

func CapabilitiesFromTags

func CapabilitiesFromTags(tags []string) Capabilities

CapabilitiesFromTags reconstructs capabilities from a flat tag list (the inverse of CapabilityTags, used when projecting a legacy flat record up to the canonical shape). A tag's presence is known-true; absence stays unknown (nil) since a flat list can't distinguish known-false from unknown.

type DeepInfraAdapter

type DeepInfraAdapter struct {
	HTTPClient *http.Client
}

DeepInfraAdapter normalizes DeepInfra's native /models/list (public, keyless) into canonical models. That endpoint — unlike the OpenAI-compatible /v1/openai/models — reports context window, per-token pricing, capability tags, type, and a deprecated flag.

func (DeepInfraAdapter) ListModels

func (a DeepInfraAdapter) ListModels(ctx context.Context) ([]CanonicalModel, error)

func (DeepInfraAdapter) Provider

func (a DeepInfraAdapter) Provider() string

type ModelAdapter

type ModelAdapter interface {
	Provider() string
	ListModels(ctx context.Context) ([]CanonicalModel, error)
}

ModelAdapter owns ALL provider-specific parsing and emits canonical models. It is the only place a provider's quirks are allowed to exist. Listing must not require an API key where the provider's model endpoint is public.

type OpenAIAdapter

type OpenAIAdapter struct {
	APIKey     string // required — OpenAI's model list is authenticated
	HTTPClient *http.Client
	Reference  *ReferenceCatalog // optional enrichment source
}

OpenAIAdapter normalizes OpenAI's /v1/models into canonical models. Unlike DeepInfra/OpenRouter, OpenAI's listing requires an API key and returns only model IDs (no capabilities/context/pricing). The adapter therefore enriches each model from a Reference catalog (typically built from OpenRouter, which lists the same models as `openai/<id>`): capabilities and context are copied with confidence, pricing is borrowed but flagged Estimated since OpenAI pricing is account-specific.

func (OpenAIAdapter) ListModels

func (a OpenAIAdapter) ListModels(ctx context.Context) ([]CanonicalModel, error)

func (OpenAIAdapter) Provider

func (a OpenAIAdapter) Provider() string

type OpenAICompatAdapter added in v0.16.2

type OpenAICompatAdapter struct {
	ProviderID string // provider identifier (e.g. "cerebras")
	BaseURL    string // full URL to /v1/models (e.g. "https://api.cerebras.ai/v1/models")
	EnvVar     string // environment variable name for the API key (e.g. "CEREBRAS_API_KEY")
	HTTPClient *http.Client
}

OpenAICompatAdapter is a generic adapter for any provider that exposes a standard OpenAI-compatible /v1/models endpoint. These providers return { "data": [{ "id": "..." }] } and require a Bearer API key for auth.

func NewOpenAICompatAdapter added in v0.16.2

func NewOpenAICompatAdapter(providerID, baseURL, envVar string) OpenAICompatAdapter

NewOpenAICompatAdapter creates a new adapter for an OpenAI-compatible provider. The ProviderID is used for credential resolution and the Provider() return value.

func (OpenAICompatAdapter) ListModels added in v0.16.2

func (a OpenAICompatAdapter) ListModels(ctx context.Context) ([]CanonicalModel, error)

func (OpenAICompatAdapter) Provider added in v0.16.2

func (a OpenAICompatAdapter) Provider() string

type OpenRouterAdapter

type OpenRouterAdapter struct {
	HTTPClient *http.Client
}

OpenRouterAdapter normalizes OpenRouter's /api/v1/models (public, keyless) into canonical models. OpenRouter is also the richest cross-provider source, so its output typically seeds the ReferenceCatalog other adapters borrow from.

func (OpenRouterAdapter) ListModels

func (a OpenRouterAdapter) ListModels(ctx context.Context) ([]CanonicalModel, error)

func (OpenRouterAdapter) Provider

func (a OpenRouterAdapter) Provider() string

type Pricing

type Pricing struct {
	InputPerMTok  float64 `json:"input_per_mtok"`
	OutputPerMTok float64 `json:"output_per_mtok"`
	CachedPerMTok float64 `json:"cached_input_per_mtok,omitempty"`
	Currency      string  `json:"currency,omitempty"` // "USD"
	Estimated     bool    `json:"estimated,omitempty"`
	Source        string  `json:"source,omitempty"` // e.g. "openrouter-reference"
}

Pricing is USD per million tokens. Estimated marks values borrowed from a reference source (e.g. OpenRouter) rather than confirmed for the caller's account — relevant where provider pricing is account-specific.

type ProbeResult

type ProbeResult struct {
	Passed       bool    `json:"passed"`
	Complex      bool    `json:"complex,omitempty"`
	Score        float64 `json:"score,omitempty"`
	LastProbedAt string  `json:"last_probed_at,omitempty"`
	ProbeVersion string  `json:"probe_version,omitempty"`
}

ProbeResult records the outcome of a capability probe. Passed is the minimum gate (model is usable for agentic edits at all); Complex additionally reports that the model cleared the discovery+scoping tier, the signal for driving primary-grade complex flows.

type ProviderFile

type ProviderFile struct {
	SchemaVersion int              `json:"schema_version"`
	Provider      string           `json:"provider"`
	GeneratedAt   string           `json:"generated_at"`
	Models        []CanonicalModel `json:"models"`
}

ProviderFile is the published per-provider canonical model file.

type ReferenceCatalog

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

ReferenceCatalog indexes canonical models by a normalized `org/model` key so adapters whose native API exposes little metadata (e.g. OpenAI) can borrow capabilities/context/modality from a richer source that lists the same model (e.g. OpenRouter, whose IDs are already `org/model`).

func NewReferenceCatalog

func NewReferenceCatalog(models []CanonicalModel) *ReferenceCatalog

NewReferenceCatalog builds a catalog from already-canonical models (typically the OpenRouter adapter's output).

func (*ReferenceCatalog) Lookup

func (c *ReferenceCatalog) Lookup(org, id string) (CanonicalModel, bool)

Lookup finds a reference model for a provider org + model ID — e.g. org="openai", id="gpt-4o" resolves "openai/gpt-4o". Returns false if absent.

Jump to

Keyboard shortcuts

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