Documentation
¶
Overview ¶
Package modelsdev is a reusable client for models.dev, the community database of model specifications, pricing, and capabilities. It fetches the static catalog.json, merges the per-provider and provider-agnostic maps into a single enriched view, validates against gross schema drift, and caches with stale-on-failure semantics. The package is a leaf: it imports no agentdex internal package, so external consumers can depend on it directly.
Index ¶
Constants ¶
const DefaultHTTPTimeout = 30 * time.Second
DefaultHTTPTimeout bounds a single catalog fetch end to end. The shared single-flight fetch detaches from any one caller's cancellation, so without an overall timeout a stalled endpoint would wedge the Client permanently. WithHTTPClient overrides it.
const DefaultTTL = 24 * time.Hour
DefaultTTL is how long a cached catalog.json is served before a refetch is attempted. On a failed refetch the stale copy is still served.
const DefaultURL = "https://models.dev/catalog.json"
DefaultURL is the published models.dev catalog fetched unless overridden.
Variables ¶
var ErrModelsSchema = errors.New("models.dev schema unrecognised")
ErrModelsSchema signals that models.dev data does not match the expected shape: empty top-level maps (gross drift, every fetch) or a requested provider with a malformed model (per-model, in Provider and Models). models.dev is unversioned community JSON, so validation is the only drift signal; this error makes drift loud rather than silent blanks. Model-resolution failures are the consuming layer's concern, not this package's.
Functions ¶
func Newer ¶
Newer reports whether a sorts before b in a newest-first listing: later release date first (ISO dates compare lexically), undated last, ties broken by id. Shared presentation order; Client.Models remains sorted by id.
func SortByRelease ¶
func SortByRelease(models []Model)
SortByRelease orders models newest release first, in place, via Newer.
Types ¶
type Benchmark ¶
type Benchmark struct {
Name string `json:"name"`
Score float64 `json:"score"`
Metric string `json:"metric"`
Source string `json:"source"`
Harness string `json:"harness"`
Dataset string `json:"dataset"`
Version string `json:"version"`
Date string `json:"date"`
Variant string `json:"variant"`
}
Benchmark is a published benchmark result for a model. Upstream it lives only in the provider-agnostic map and is merged onto the matching provider model.
type Catalog ¶
type Catalog struct {
Models map[string]Model `json:"models"` // provider-agnostic, keyed by path-style model id
Providers map[string]Provider `json:"providers"` // keyed by provider id
}
Catalog is the merged result of fetching models.dev catalog.json: the provider-agnostic model map plus the per-provider map, mirroring the upstream { models, providers } shape. Distinct from agentdex's index of known coding agents.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client fetches, caches, merges, and serves the models.dev catalog. Fetch, decode, and merge happen once per Client; the merged catalog is memoised in memory. A long-lived Client never re-merges — refresh needs a new Client. Methods are safe for concurrent use.
func New ¶
func New(opts ...ClientOption) *Client
New constructs a Client with built-in defaults: the published catalog URL, the cache directory under $XDG_CACHE_HOME, a 24h TTL, and a package-owned HTTP client. Options override any of these.
func (*Client) Catalog ¶
Catalog returns the merged catalog. The first call fetches, caches, and merges; later calls return the memoised copy. The returned pointer is shared and must be treated as read-only.
func (*Client) Models ¶
Models returns the merged models of the named providers, sorted by id. The per-model check is applied only to those providers; a malformed model raises ErrModelsSchema. Unknown provider ids are skipped. Returned models alias the memoised catalog and must be treated as read-only.
func (*Client) Provider ¶
Provider returns one provider by id, whether it was found, and any error. found reports existence only and is independent of the error. A provider that exists but carries a malformed model returns found true with ErrModelsSchema, so branching on found alone cannot swallow schema drift as absence. The per-model check is applied to that provider only. The returned Provider shares the memoised catalog and must be treated as read-only.
func (*Client) Stale ¶
Stale reports whether the memoised catalog was served from the stale-fallback path: a network fetch failed and a previously cached copy was re-decoded. Meaningful only after a successful load; before any load, and after a failed load with no cache, it returns false. Within-TTL hit and fresh fetch both report false.
type ClientOption ¶
type ClientOption func(*Client)
ClientOption configures a Client.
func WithCacheDir ¶
func WithCacheDir(dir string) ClientOption
WithCacheDir overrides the stale-cache directory.
func WithForceRefresh ¶
func WithForceRefresh() ClientOption
WithForceRefresh makes the next load fetch fresh bytes, ignore the cache TTL, and report fetch/decode failure rather than fall back to stale cache. Honest mode for explicit refresh: the caller learns whether fresh data was fetched. A successful fetch still updates the on-disk cache.
func WithHTTPClient ¶
func WithHTTPClient(hc *http.Client) ClientOption
WithHTTPClient overrides the package-owned HTTP client, replacing the default timeout backstop. A consumer that supplies a client without a timeout takes on responsibility for bounding the fetch through the request context.
func WithURL ¶
func WithURL(url string) ClientOption
WithURL overrides the catalog URL (mirror or frozen snapshot).
type Cost ¶
type Cost struct {
Input float64 `json:"input"`
Output float64 `json:"output"`
Reasoning float64 `json:"reasoning"`
CacheRead float64 `json:"cache_read"`
CacheWrite float64 `json:"cache_write"`
InputAudio float64 `json:"input_audio"`
OutputAudio float64 `json:"output_audio"`
ContextOver200K *Cost `json:"context_over_200k"` // nil when flat
Tiers []Tier `json:"tiers"` // nil when flat
}
Cost is per-token pricing in USD per 1,000,000 tokens.
type Limit ¶
type Limit struct {
Context int `json:"context"`
Input int `json:"input"`
Output int `json:"output"`
}
Limit holds a model's token limits. An absent upstream limit decodes to the zero value, legitimate for media-generation models that carry no token limit.
type Modalities ¶
Modalities lists the input and output media a model accepts and produces, each element one of text|audio|image|video|pdf.
type Model ¶
type Model struct {
ID string `json:"id"`
Name string `json:"name"`
Family string `json:"family"`
Attachment bool `json:"attachment"`
Reasoning bool `json:"reasoning"`
ToolCall bool `json:"tool_call"`
StructuredOutput bool `json:"structured_output"`
Temperature bool `json:"temperature"`
Knowledge string `json:"knowledge"` // YYYY-MM or YYYY-MM-DD
ReleaseDate string `json:"release_date"`
LastUpdated string `json:"last_updated"`
Modalities Modalities `json:"modalities"`
OpenWeights bool `json:"open_weights"`
Limit Limit `json:"limit"`
Cost *Cost `json:"cost"` // USD per 1,000,000 tokens; nil if unknown
Status string `json:"status"` // alpha|beta|deprecated
Benchmarks []Benchmark `json:"benchmarks"`
Weights []Weight `json:"weights"`
}
Model is one model entry. The same type serves both maps: in Catalog.Models its ID is the path-style provider-agnostic id; within a Provider.Models it is the short id local to that provider. ID is never normalised across the two.
type Provider ¶
type Provider struct {
ID string `json:"id"`
Name string `json:"name"`
Doc string `json:"doc"`
NPM string `json:"npm"`
API string `json:"api"`
Env []string `json:"env"` // API-key env var names
Models map[string]Model `json:"models"`
}
Provider is one models.dev provider and the models it offers.
type Tier ¶
type Tier struct {
Input float64 `json:"input"`
Output float64 `json:"output"`
CacheRead float64 `json:"cache_read"`
CacheWrite float64 `json:"cache_write"`
Tier TierDimension `json:"tier"`
}
Tier is one entry in a model's tiered pricing: a per-token cost subset plus the dimension and threshold at which it applies. Upstream nests the dimension under a "tier" object.
type TierDimension ¶
type TierDimension struct {
Type string `json:"type"` // e.g. "context"
Size int `json:"size"` // threshold, e.g. 200000
}
TierDimension is the nested "tier" object on each tiered-pricing entry.