Documentation
¶
Overview ¶
Package providercatalog is a stdlib-only LEAF DATA adapter exposing a pinned, embed-vendored subset of the models.dev model catalog as a typed, read-only Go API. It carries no behaviour beyond parsing the embedded JSON once and handing out immutable-by-convention value types; nothing here knows about the agent, providers, ports, or the domain.
Source, provenance, and license ¶
The embedded data in models.dev.curated.json is a subset of the community model catalog published at:
https://models.dev/api.json
canonical repository https://github.com/anomalyco/models.dev, distributed under the MIT License ("Copyright (c) 2025 models.dev"). The full MIT license text + attribution is vendored alongside this file in MODELS_DEV_LICENSE, as the MIT license requires when redistributing portions of the work.
The catalog API exposes NO version field (the upstream endpoint has none), so the fetch date IS the pin. Pinned 2026-07-13.
Curation policy (full vendor for in-scope providers) ¶
The full catalog has 145+ providers and thousands of models. We vendor ONLY the three providers in scope for multi-provider Phase 0/1 — but for each of them we vendor ALL models (no hand-pinned allowlist). The DROPPED surface, stated plainly:
- 142+ providers dropped wholesale (out of P0/P1 scope: Chat-Completions providers like Gemini-native / Together are P2 and need their own adapter, so their catalog entries are not useful yet).
- openai: ALL models vendored (P0 native via the Responses adapter).
- anthropic: ALL models vendored (P1 native Messages adapter).
- openrouter: ALL models vendored (the OpenRouter flagship+long-tail set — hundreds of routes across dozens of upstream providers).
The catalog is kept fresh by a weekly CI job (.github/workflows/catalog-refresh.yml) that re-fetches models.dev/api.json, regenerates the curated JSON, and opens a PR if it changed. An unknown provider/model id is an honest (_, false) lookup miss, never a silent substitution. The Go structs deliberately do NOT parse cost / release_date / knowledge etc.; the curated JSON KEEPS those fields (the jq projection copies whole model objects) so a future slice can surface them without re-pinning (encoding/json ignores unmapped fields).
Deterministic regeneration (reproducible re-pin) ¶
The curated file is generated from the full source by ONE deterministic jq filter; -S (sort keys) makes the embedded bytes stable across re-pins so a diff shows only real model changes. To re-pin:
# 1. Re-fetch the pinned source (record the date in the comment above):
curl -s https://models.dev/api.json > .scratch/models.dev.full.json
# 2. Regenerate the curated subset deterministically (ALL models for the 3
# in-scope providers — no allowlist):
jq -S '{
openai: ( .openai | {id, env, npm, api, name, doc, models} ),
anthropic: ( .anthropic | {id, env, npm, api, name, doc, models} ),
openrouter: ( .openrouter | {id, env, npm, api, name, doc, models} )
}' .scratch/models.dev.full.json > internal/adapter/providercatalog/models.dev.curated.json
Layering ¶
LEAF adapter: stdlib + embed + encoding/json ONLY. It imports NO domain (session/prompt/tool/governance), NO port, NO internal/app, and NO other adapter. Its Catalog/Provider/Model are package-own value types and must never leak into the domain or port. Only the composition layer (internal/app) reads it.
Index ¶
- type Catalog
- type Model
- func (m Model) ContextLimit() int
- func (m Model) Family() string
- func (m Model) ID() string
- func (m Model) InputLimit() int
- func (m Model) InputModalities() []string
- func (m Model) Name() string
- func (m Model) OutputLimit() int
- func (m Model) SupportsAttachment() bool
- func (m Model) SupportsImageInput() bool
- func (m Model) SupportsReasoning() bool
- func (m Model) SupportsToolCall() bool
- type Provider
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Catalog ¶
type Catalog struct {
// contains filtered or unexported fields
}
Catalog is the parsed, read-only curated catalog. It is constructed once from the embedded JSON and is immutable; accessors return defensive copies so a caller can never corrupt the singleton.
func Default ¶
func Default() *Catalog
Default returns the process-wide parsed catalog, parsed exactly once.
Parse-failure posture: the JSON is compiled into the binary via go:embed, so a parse failure is a build/test-time defect (a corrupted embed), NOT a runtime fail-safe condition. Default therefore PANICS on a parse error rather than threading an impossible error through every S3/S5 call site — the same idiom as regexp.MustCompile / template.Must. The package guard test makes shipping a broken embed impossible.
type Model ¶
type Model struct {
// contains filtered or unexported fields
}
Model is one curated model's metadata. Fields are chosen for S3 (the ListModels projection) and S5 (capability intersection) — nothing is computed at parse time, only data is carried.
func (Model) ContextLimit ¶
ContextLimit returns the total context window (limit.context).
func (Model) ID ¶
ID returns the model's catalog id (e.g. "gpt-5", or "anthropic/claude-opus-4.5" for an openrouter route).
func (Model) InputLimit ¶
InputLimit returns the max input tokens (limit.input).
func (Model) InputModalities ¶
InputModalities returns the raw input-modality list ("text","image","audio"). S5 intersects this against the adapter's port.ProviderCapabilities; a fresh copy is returned so the singleton cannot be mutated.
func (Model) OutputLimit ¶
OutputLimit returns the max output tokens (limit.output).
func (Model) SupportsAttachment ¶
SupportsAttachment reports whether the model accepts file attachments.
func (Model) SupportsImageInput ¶
SupportsImageInput reports whether "image" is among the input modalities (a convenience derivation for S5's capability intersection).
func (Model) SupportsReasoning ¶
SupportsReasoning reports whether the model exposes reasoning (for S5).
func (Model) SupportsToolCall ¶
SupportsToolCall reports whether the model supports tool/function calls.
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider is one vendored provider's metadata plus its curated model set. It is handed out BY VALUE with unexported fields, so a returned Provider cannot mutate the catalog.
func (Provider) APIBaseURL ¶
APIBaseURL returns the provider's API base URL; "" means use the SDK default (openai/anthropic). For openrouter it is the OpenRouter base URL.
func (Provider) EnvVars ¶
EnvVars returns the credential env-var names whose non-empty value makes this provider AVAILABLE (any one suffices). This is the array internal/app's registry reads to replace its former inline env map. It stays HONEST to upstream — e.g. openrouter is ["OPENROUTER_API_KEY"] only; the mecatl OPENAI_API_KEY fallback is a COMPOSITION augmentation, not catalog data. A fresh copy is returned so a caller cannot mutate the singleton.
func (Provider) ID ¶
ID returns the provider's stable, lowercase id (matches the registry's provider id constants and the wire provider_id).