Model Registry
Dynamic model registry with pricing, capabilities, and multi-provider support.
Overview
The @cogitator-ai/models package provides a dynamic model registry that tracks pricing, context windows, and capabilities for LLM models across all major providers. It fetches data from LiteLLM and includes built-in fallbacks.
import { initializeModels, getModel, getPrice, listModels } from '@cogitator-ai/models';
await initializeModels();
const model = getModel('gpt-6.1-sol');
console.log(model?.contextWindow); // 1050000
console.log(model?.capabilities?.supportsVision); // true
const price = getPrice('claude-sonnet-5-5');
console.log(`$${price?.input}/M input, $${price?.output}/M output`);Model ids are matched case-insensitively and aliases resolve too (claude-sonnet-5.5 → claude-sonnet-5-5). Lookups return null for unknown models.
Provider-qualified ids
The same model is often sold by several providers at different prices, so the registry keeps one entry per provider. Each entry's id is the model's name at that provider, provider is the registry's provider id, and catalogId is the key LiteLLM lists it under:
await initializeModels();
getModel('openrouter/deepseek/deepseek-v4-pro');
// { id: 'deepseek/deepseek-v4-pro', provider: 'openrouter',
// catalogId: 'openrouter/deepseek/deepseek-v4-pro', pricing: { input: 0.2088, output: 0.4176 }, ... }
getModel('azure_ai/deepseek-v4-pro')?.provider; // 'azure', at Azure's price
getModel('google/gemini-3.8-flash')?.id; // 'gemini-3.8-flash' (also found as gemini/gemini-3.8-flash)A lookup resolves in this order:
- A provider-qualified id finds that provider's entry. Both Cogitator model strings (
openai/gpt-6.1-sol,google/gemini-3.8-flash,openrouter/deepseek/deepseek-v4-pro) and LiteLLM keys (gemini/...,azure_ai/...) work. - When that provider does not list the model, the prefix is dropped and the rest is looked up, so
openai/deepseek/deepseek-v4-pro(an OpenAI-compatible server) is priced asdeepseek/deepseek-v4-pro. - A bare name (
deepseek-v4-pro) picks one listing by fixed rules, never by catalogue order: active models before deprecated ones, the vendor's own listing (a built-in model or an unprefixed LiteLLM key) before resellers, then the providers inBUILTIN_PROVIDERSorder, then the shorter id, then alphabetically.
Pass the full model string your agent runs on to get that provider's price. The built-in models follow the same rules before initializeModels() runs.
Pricing and Cost
Prices are USD per million tokens. getPrice() returns only input and output; getPricing() returns the full ModelPricing, including prompt-cache prices:
import { getPricing, calculateCost } from '@cogitator-ai/models';
getPricing('claude-sonnet-5-5');
// { input: 2, output: 10, inputCached: 0.2, inputCacheWrite: 2.5 }
const cost = calculateCost('claude-sonnet-5-5', {
inputTokens: 10_000,
outputTokens: 1_000,
cachedInputTokens: 8_000, // part of inputTokens read from the cache
cacheWriteTokens: 0, // part of inputTokens written to the cache
});
// 0.0156 (USD), or null when the model's price is unknownCache reads and writes are charged at inputCached / inputCacheWrite where the model has them, and at the input price otherwise. RunResult.usage.cost adds up the cost of each model call. When the provider reports what a call cost (OpenRouter does, in usage.cost), the runtime takes that price, which also reflects which upstream served the call. Other calls are priced with calculateCost() on the shared registry, using the full model string the agent runs on, so a model the registry does not know and whose provider reports nothing costs 0. Call initializeModels() at startup to price more than the built-in models.
ModelRegistry
The ModelRegistry class manages model data with caching and auto-refresh.
import { ModelRegistry } from '@cogitator-ai/models';
const registry = new ModelRegistry({
cache: {
ttl: 24 * 60 * 60 * 1000,
storage: 'file',
filePath: './cache/models.json',
},
autoRefresh: true,
refreshInterval: 24 * 60 * 60 * 1000,
fallbackToBuiltin: true,
});
await registry.initialize();Options
| Option | Default | Description |
|---|---|---|
cache.ttl | 24 hours | Cache time-to-live in milliseconds |
cache.storage | 'memory' | 'memory' or 'file' |
cache.filePath | ~/.cogitator/models-cache.json | File path for file-based cache (in memory where there is no file system, e.g. edge runtimes) |
autoRefresh | false | Automatically refresh data in background |
refreshInterval | 24 hours | Refresh interval in milliseconds |
fallbackToBuiltin | true | Use built-in models when fetch fails |
Methods
initialize() loads a fresh cache if there is one (and refreshes it in the background), otherwise fetches LiteLLM data; on failure it falls back to built-in models (or throws when fallbackToBuiltin is false). Lookups before initialize() load the built-in models.
registry.getModel('gpt-6.1-sol');
registry.getPrice('gpt-6.1-sol');
registry.getPricing('gpt-6.1-sol');
registry.listModels({ provider: 'openai', supportsTools: true });
registry.listProviders();
registry.getProvider('anthropic');
registry.getModelCount();
registry.isInitialized();
await registry.refresh();
registry.shutdown();Filtering
Use ModelFilter to query models by provider, capabilities, and cost:
import { listModels } from '@cogitator-ai/models';
const visionModels = listModels({ supportsVision: true, excludeDeprecated: true });
const cheapToolModels = listModels({
supportsTools: true,
maxPricePerMillion: 1.0,
});
const largeContext = listModels({
minContextWindow: 200_000,
provider: 'anthropic',
});Filter Options
| Filter | Type | Description |
|---|---|---|
provider | string | Filter by provider ID |
supportsTools | boolean | Filter by tool/function calling support |
supportsVision | boolean | Filter by vision/image support |
minContextWindow | number | Minimum context window size |
maxPricePerMillion | number | Max average price per million tokens |
excludeDeprecated | boolean | Exclude deprecated models |
Built-in Providers
The registry includes provider entries (BUILTIN_PROVIDERS) for 16 providers:
OpenAI (openai), Anthropic (anthropic), Google (google), Ollama (ollama), Azure OpenAI (azure), AWS Bedrock (aws), Mistral AI (mistral), Cohere (cohere), Groq (groq), Together AI (together), Fireworks AI (fireworks), DeepInfra (deepinfra), Perplexity (perplexity), Replicate (replicate), xAI (xai), OpenRouter (openrouter).
Built-in model data covers OpenAI, Anthropic and Google; models of the other providers, and additional providers, come from LiteLLM data once it is fetched. getProvider(id).models lists the model ids loaded for a provider.
Built-in Models
Built-in fallbacks cover current model families for major providers, including OpenAI GPT-6 (gpt-6-astra, gpt-6.1-sol, gpt-6-luna) and GPT-5.6/5.5, Anthropic Claude Opus 5.5 / Sonnet 5.5 / Fable 5.1 / Haiku 4.5, and Google Gemini 3.8 Flash / Gemini 3.5 Flash-Lite / Gemini 3.1 Pro Preview.
Retired or retiring models stay in the registry with deprecated: true so lookups and pricing keep working for existing configs — among them o3, o3-mini, o3-pro, o4-mini, gpt-4.1-nano, gpt-5.4-nano, gpt-4, gpt-4-turbo, claude-sonnet-4, claude-opus-4, claude-opus-4-1, the Claude 3.x models, and Gemini 2.5 / 2.0 / 1.5. Use excludeDeprecated: true (or filter on model.deprecated) to skip them.
import {
BUILTIN_MODELS,
OPENAI_MODELS,
ANTHROPIC_MODELS,
GOOGLE_MODELS,
} from '@cogitator-ai/models';
const activeOpenAI = OPENAI_MODELS.filter((model) => !model.deprecated);
const cheapToolModels = BUILTIN_MODELS.filter(
(model) =>
model.capabilities?.supportsTools && (model.pricing.input + model.pricing.output) / 2 <= 5
);Caching
Models data is cached to avoid repeated network requests:
// Memory cache (default)
new ModelRegistry({ cache: { ttl: 3600000, storage: 'memory' } });
// File cache (persists across restarts)
new ModelRegistry({
cache: { ttl: 86400000, storage: 'file', filePath: './models-cache.json' },
});The cache supports stale-while-revalidate: if a refresh fails, the registry falls back to stale cached data before using built-in models. Fetched data is merged over the built-in entries, so built-in models keep their display names and aliases with fresh prices.
ModelCache is exported for direct use (get(), getStale(), set(models), clear()).
LiteLLM Integration
For advanced use cases, you can fetch and transform LiteLLM data directly:
import { fetchLiteLLMData, transformLiteLLMData } from '@cogitator-ai/models';
const rawData = await fetchLiteLLMData();
const models = transformLiteLLMData(rawData);Zod Schemas
All types have corresponding Zod schemas for runtime validation:
import {
ModelInfoSchema,
ModelPricingSchema,
ModelCapabilitiesSchema,
ProviderInfoSchema,
} from '@cogitator-ai/models';
const result = ModelInfoSchema.safeParse(unknownData);
if (result.success) {
console.log(result.data.id);
}Global Functions
Convenience functions use a shared default registry:
import {
initializeModels,
getModel,
getPrice,
listModels,
getModelRegistry,
shutdownModels,
} from '@cogitator-ai/models';
await initializeModels();
getModel('gpt-6.1-sol');
getPrice('claude-sonnet-5-5');
listModels({ provider: 'google' });
shutdownModels();These functions auto-initialize with built-in data on first use, so initializeModels() is optional but recommended for fetching latest data. The shared registry (getModelRegistry()) caches to the file ~/.cogitator/models-cache.json for 24 hours; shutdownModels() stops it and discards it, so the next call creates a new one.