npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cogitator-ai/models

v18.6.0

Published

Dynamic model registry with pricing for Cogitator

Readme

@cogitator-ai/models

Dynamic model registry with pricing information for Cogitator. Fetches up-to-date model data from LiteLLM and OpenRouter's public model list, and works offline from built-in models and bundled copies of both.

Installation

pnpm add @cogitator-ai/models

@cogitator-ai/core uses this registry to price runs (result.usage.cost), under the prices of your own in llm.pricing, and to pick models for cost-aware routing. See Model Registry on the website.

Features

  • Dynamic Data - Fetches latest model info from LiteLLM, and openrouter/* prices from OpenRouter's own model list
  • Pricing Information - Input, output and prompt-cache costs per million tokens, calculateCost() prices token usage, ModelPricer puts prices of your own over the registry
  • Capability Tracking - Vision, tools, streaming, JSON mode support
  • Multi-Provider - OpenAI, Anthropic, Google, Ollama, Azure, AWS, and more
  • Caching - Memory or file-based cache with configurable TTL
  • Offline Catalogue - Built-in models and bundled LiteLLM and OpenRouter snapshots when external data is unavailable
  • Filtering - Query models by provider, capabilities, price

Quick Start

import { initializeModels, getModel, getPrice, listModels } from '@cogitator-ai/models';

await initializeModels();

const model = getModel('gpt-6.1-sol');
console.log(model?.contextWindow);
console.log(model?.capabilities?.supportsVision);

const price = getPrice('claude-sonnet-5-5');
console.log(`Input: $${price?.input}/M tokens`);
console.log(`Output: $${price?.output}/M tokens`);

const toolModels = listModels({
  supportsTools: true,
  provider: 'openai',
});

Lookups are case-insensitive and resolve aliases. Calling them before initializeModels() works too: the registry then uses the offline catalogue, with the same lookup rules, and initializeModels() still loads the current one whenever it runs.

Provider-qualified ids

The registry keeps one entry per provider, so a model sold by several providers keeps each provider's price. id is the model's name at its provider and catalogId the key its catalogue lists it under (openrouter/<id> for a model of OpenRouter's list):

await initializeModels();

getModel('openrouter/deepseek/deepseek-v4-pro');
// { id: 'deepseek/deepseek-v4-pro', provider: 'openrouter',
//   catalogId: 'openrouter/deepseek/deepseek-v4-pro',
//   pricing: { input: 0.888966, output: 1.777932, inputCached: 0.0740805 }, ... }

getModel('deepseek/deepseek-v4-pro'); // DeepSeek's own price, { input: 1.32, output: 3.96, ... }

getModel('openai/gpt-6.1-sol'); // Cogitator model strings work
getModel('azure_ai/deepseek-v4-pro'); // and so do LiteLLM keys, at that provider's price
  • A provider-qualified id finds that provider's entry. openrouter/* models are priced from OpenRouter's public model list (https://openrouter.ai/api/v1/models, no key needed), as OpenRouter bills them, not at the vendor's direct price. OpenRouter's vendor names z-ai and x-ai are read as the providers zai and xai.
  • When that provider does not list the model, the prefix is dropped and the rest is looked up (openai/deepseek/deepseek-v4-pro is priced as deepseek/deepseek-v4-pro).
  • A bare name picks one listing by fixed rules, never by catalogue order: active before deprecated, the vendor's own listing (a built-in model or an unprefixed LiteLLM key) before resellers, then the providers in BUILTIN_PROVIDERS order, then the shorter id, then alphabetically.

Price runs with the full model string the agent runs on (calculateCost('openrouter/deepseek/deepseek-v4-pro', usage)).


Model Registry

The ModelRegistry class manages model data with caching and auto-refresh.

Initialization

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();

Configuration Options

interface RegistryOptions {
  cache?: CacheOptions;
  autoRefresh?: boolean;
  refreshInterval?: number;
  fallbackToBuiltin?: boolean;
}

interface CacheOptions {
  ttl: number;
  storage: 'memory' | 'file';
  filePath?: string;
}

| Option | Default | Description | | ------------------- | -------------------------------- | ------------------------------------ | | cache.ttl | 24 hours | Cache time-to-live in milliseconds | | cache.storage | 'memory' | Storage backend | | cache.filePath | ~/.cogitator/models-cache.json | File path for file-based cache | | autoRefresh | false | Enable automatic background refresh | | refreshInterval | 24 hours | Refresh interval in milliseconds | | fallbackToBuiltin | true | Use the offline catalogue on failure |

initialize() uses a fresh cache when there is one (and refreshes in the background), otherwise fetches LiteLLM data and OpenRouter's model list, fetched models are merged with the built-in ones, OpenRouter's prices over LiteLLM's for openrouter/*. When the LiteLLM fetch fails it falls back to a stale cache, then to the offline catalogue (or throws with fallbackToBuiltin: false). When only OpenRouter cannot be fetched, the bundled copy of its list takes its place, over LiteLLM as offline, with a warning, and the catalogue stays fresh in the cache for 15 minutes instead of the whole ttl, so the next load asks OpenRouter again.

Offline Catalogue

The offline catalogue is the built-in models plus every priced model of the copy of the LiteLLM catalogue bundled with the package (LITELLM_SNAPSHOT, with LiteLLM's MIT notice) and of the copy of OpenRouter's model list (OPENROUTER_SNAPSHOT, the priced models that answer in text), the built-in models priced and sized from those copies. A model the live catalogue lists without a price keeps its context window and capabilities but carries priceUnknown: true, and getPrice, getPricing and calculateCost answer null for it instead of a price of zero. It answers lookups before initializeModels() and when both the fetch and the cache fail, so DeepSeek, Mistral, Bedrock, OpenRouter and the rest are priced without the network.

import { getPricing, LITELLM_SNAPSHOT, OPENROUTER_SNAPSHOT } from '@cogitator-ai/models';

getPricing('deepseek/deepseek-chat'); // from the bundled copy, before initializeModels()
LITELLM_SNAPSHOT.fetchedAt; // the day the copy was made, 'YYYY-MM-DD'
LITELLM_SNAPSHOT.source; // the LiteLLM catalogue URL at the commit the copy was made from
OPENROUTER_SNAPSHOT.fetchedAt; // the day the OpenRouter copy was made

pnpm --filter @cogitator-ai/models snapshot refreshes both copies in the repository, keeping the models that answer text and the fields the registry reads.

Registry Methods

await registry.initialize();

const model = registry.getModel('gpt-6.1-sol');

const price = registry.getPrice('claude-sonnet-5-5'); // { input, output } per million tokens
const pricing = registry.getPricing('claude-sonnet-5-5'); // full ModelPricing incl. cache prices

const models = registry.listModels({
  provider: 'anthropic',
  supportsVision: true,
});

const providers = registry.listProviders();

const provider = registry.getProvider('openai');

console.log(registry.getModelCount());
console.log(registry.isInitialized());

await registry.refresh();

registry.shutdown();

Global Functions

For convenience, the package provides global functions that use a default registry (file cache at ~/.cogitator/models-cache.json, 24 h TTL, offline fallback):

import {
  initializeModels,
  getModel,
  getPrice,
  getPricing,
  calculateCost,
  isDecisionModel,
  listModels,
  getModelRegistry,
  shutdownModels,
} from '@cogitator-ai/models';

await initializeModels();

const model = getModel('gpt-6.1-sol');
const price = getPrice('gpt-6.1-sol');
const pricing = getPricing('gpt-6.1-sol');
const allModels = listModels();

// USD for a call; cached and cache-write tokens are parts of inputTokens
const cost = calculateCost('claude-sonnet-5-5', {
  inputTokens: 12_000,
  outputTokens: 800,
  cachedInputTokens: 10_000,
  cacheWriteTokens: 0,
  cacheWrite1hTokens: 0, // part of cacheWriteTokens written with the 1-hour TTL
}); // null when the model's price is unknown

isDecisionModel('openrouter/typesafe/jev-1.13'); // true: it answers through cog.decide(), not chat

const registry = getModelRegistry();
const count = registry.getModelCount();

shutdownModels();

Prices of Your Own

ModelPricer prices model calls from prices of your own first and the registry second, the way @cogitator-ai/core does with llm.pricing. A key matches the model string or its tail after any /, the longest match first, case-insensitively: openai/gpt-4o prices that model string and the ones that end in it, such as openrouter/openai/gpt-4o, gpt-4o the model at every provider that serves it under that name.

import { ModelPricer, costOf, getPricing, type PricingOverrides } from '@cogitator-ai/models';

const overrides: PricingOverrides = { 'my-finetune': { input: 0.3, output: 1.2 } };
const pricer = new ModelPricer(overrides);

pricer.pricing('openai/my-finetune'); // { input: 0.3, output: 1.2 }
pricer.cost('openai/my-finetune', { inputTokens: 10_000, outputTokens: 500 }); // 0.0036, null when unknown
pricer.hasOverride('claude-sonnet-5-5'); // false: priced from the registry

costOf(getPricing('claude-sonnet-5-5')!, { inputTokens: 1000, outputTokens: 100 }); // USD at a given price

Model Information

ModelInfo Type

interface ModelInfo {
  id: string; // the model's name at its provider
  provider: string;
  catalogId?: string; // the LiteLLM key, e.g. 'openrouter/deepseek/deepseek-v4-pro'
  displayName: string;
  pricing: ModelPricing;
  contextWindow: number;
  maxOutputTokens?: number;
  capabilities?: ModelCapabilities;
  deprecated?: boolean;
  aliases?: string[];
  kind?: 'chat' | 'decision'; // decision models answer typed questions through cog.decide()
}

interface ModelPricing {
  input: number; // USD per million input tokens
  output: number; // USD per million output tokens
  inputCached?: number; // cache reads
  inputCacheWrite?: number; // cache writes (5-minute TTL)
  inputCacheWrite1h?: number; // cache writes with the 1-hour TTL (Anthropic)
  outputCached?: number;
}

interface ModelCapabilities {
  supportsVision?: boolean;
  supportsTools?: boolean;
  supportsFunctions?: boolean;
  supportsStreaming?: boolean;
  supportsJson?: boolean;
}

Example Model

const model = getModel('gpt-6.1-sol');
// {
//   id: 'gpt-6.1-sol',
//   provider: 'openai',
//   displayName: 'GPT-6.1 Sol',
//   pricing: { input: 2, output: 10, inputCached: 0.1 },
//   contextWindow: 1050000,
//   maxOutputTokens: 128000,
//   capabilities: {
//     supportsTools: true,
//     supportsVision: true,
//     supportsFunctions: true,
//     supportsStreaming: true,
//     supportsJson: true,
//   }
// }

Values shown are the built-in fallback entry; after initializeModels() the data may come from LiteLLM instead.


Filtering Models

Use ModelFilter to query specific models:

interface ModelFilter {
  provider?: string;
  supportsTools?: boolean;
  supportsVision?: boolean;
  minContextWindow?: number;
  maxPricePerMillion?: number;
  excludeDeprecated?: boolean;
}

supportsTools and supportsVision accept both true and false (a model without the capability flag counts as false). maxPricePerMillion compares the average of the input and output price.

Filter Examples

const openaiModels = listModels({
  provider: 'openai',
});

const visionModels = listModels({
  supportsVision: true,
});

const toolModels = listModels({
  supportsTools: true,
  excludeDeprecated: true,
});

const largeContext = listModels({
  minContextWindow: 100000,
});

const cheapModels = listModels({
  maxPricePerMillion: 1.0,
});

const anthropicVision = listModels({
  provider: 'anthropic',
  supportsVision: true,
  supportsTools: true,
});

Providers

Built-in Providers

import { BUILTIN_PROVIDERS } from '@cogitator-ai/models';

| Provider | Website | | ------------ | ---------------------- | | OpenAI | openai.com | | Anthropic | anthropic.com | | Google | ai.google.dev | | Ollama | ollama.com | | Azure OpenAI | azure.microsoft.com | | AWS Bedrock | aws.amazon.com/bedrock | | Mistral AI | mistral.ai | | Cohere | cohere.com | | Groq | groq.com | | Together AI | together.ai | | Fireworks AI | fireworks.ai | | DeepInfra | deepinfra.com | | Perplexity | perplexity.ai | | Replicate | replicate.com | | xAI | x.ai | | OpenRouter | openrouter.ai |

Provider Information

interface ProviderInfo {
  id: string;
  name: string;
  website?: string;
  models: string[];
}

const providers = registry.listProviders();
const openai = registry.getProvider('openai');
console.log(openai?.models.length);

Built-in Models

The built-in models carry display names and aliases, and are part of the offline catalogue:

import {
  BUILTIN_MODELS,
  OPENAI_MODELS,
  ANTHROPIC_MODELS,
  GOOGLE_MODELS,
  OPENROUTER_MODELS,
} from '@cogitator-ai/models';

OPENROUTER_MODELS has the models only OpenRouter serves, which the LiteLLM catalogue does not describe: TypeSafe's Jev (typesafe/jev-1.13, kind: 'decision'), $0.042 per million input tokens, free output, 32 000 tokens of context.

Deprecated entries stay in the registry (with deprecated: true) so pricing and lookups keep working for existing configs; use excludeDeprecated: true to hide them.

OpenAI Models

  • gpt-6-astra, gpt-6.1-sol, gpt-6-sol, gpt-6-luna
  • gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna
  • gpt-5.5, gpt-5.5-pro
  • gpt-5.4, gpt-5.4-mini, gpt-5.4-pro
  • gpt-4.1, gpt-4.1-mini
  • gpt-4o, gpt-4o-mini
  • Deprecated: gpt-5.4-nano, gpt-4.1-nano, o3, o3-mini, o3-pro, o4-mini, o1, o1-mini, o1-preview, gpt-4-turbo, gpt-4, gpt-3.5-turbo

Anthropic Models

  • claude-fable-5-1, claude-opus-5-5, claude-sonnet-5-5
  • claude-opus-5, claude-sonnet-5, claude-fable-5
  • claude-opus-4-8, claude-opus-4-7, claude-opus-4-6, claude-sonnet-4-6
  • claude-opus-4-5, claude-sonnet-4-5, claude-haiku-4-5
  • Deprecated: claude-opus-4-1, claude-sonnet-4, claude-opus-4, claude-3-7-sonnet, claude-3-5-sonnet, claude-3-5-haiku, claude-3-opus, claude-3-haiku

Google Models

  • gemini-3.8-flash, gemini-3.5-flash-lite, gemini-3.5-flash
  • gemini-3.1-pro-preview, gemini-3-flash-preview, gemini-3.1-flash-lite
  • Deprecated: gemini-3.1-flash-lite-preview, gemini-3-pro-preview, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, gemini-2.0-flash, gemini-2.0-flash-lite, gemini-1.5-pro, gemini-1.5-flash, gemini-1.5-flash-8b

Aliases resolve to the canonical id, for example gemini-flash / gemini-3-flash → gemini-3.8-flash, gemini-flash-lite / gemini-3-flash-lite → gemini-3.5-flash-lite, claude-sonnet-5.5 → claude-sonnet-5-5.


Caching

Memory Cache

const registry = new ModelRegistry({
  cache: {
    ttl: 60 * 60 * 1000,
    storage: 'memory',
  },
});

File Cache

const registry = new ModelRegistry({
  cache: {
    ttl: 24 * 60 * 60 * 1000,
    storage: 'file',
    filePath: './cache/models.json',
  },
});

ModelCache Class

import { BUILTIN_MODELS, ModelCache } from '@cogitator-ai/models';

const cache = new ModelCache({
  ttl: 3600000,
  storage: 'file',
  filePath: './models-cache.json',
});

const models = await cache.get(); // null when missing or older than ttl

await cache.set(BUILTIN_MODELS);

const staleData = await cache.getStale(); // ignores the TTL

await cache.clear();

Data Fetching

LiteLLM Integration

import { fetchLiteLLMData, transformLiteLLMData } from '@cogitator-ai/models';

const rawData = await fetchLiteLLMData();

const models = transformLiteLLMData(rawData);

OpenRouter Integration

import { fetchOpenRouterData, transformOpenRouterData } from '@cogitator-ai/models';

const entries = await fetchOpenRouterData(); // every page of GET /api/v1/models, checked with OpenRouterModelEntrySchema

const models = transformOpenRouterData(entries); // provider 'openrouter', catalogId 'openrouter/<id>'

Routers whose price depends on the model they pick (openrouter/auto, a price of -1) carry priceUnknown: true, models past their expiration_date are deprecated, and models that do not answer in text are left out. Time and prompt-size price overrides are not applied, the base price is used.

LiteLLM Data Structure

interface LiteLLMModelEntry {
  max_tokens?: number;
  max_input_tokens?: number;
  max_output_tokens?: number;
  input_cost_per_token?: number;
  output_cost_per_token?: number;
  cache_read_input_token_cost?: number;
  cache_creation_input_token_cost?: number;
  litellm_provider?: string;
  mode?: string;
  supports_function_calling?: boolean;
  supports_vision?: boolean;
  supports_response_schema?: boolean;
  supports_tool_choice?: boolean;
  deprecation_date?: string;
  // ...and a few more LiteLLM fields
}

Examples

Cost Calculator

import { calculateCost } from '@cogitator-ai/models';

const cost = calculateCost('gpt-6.1-sol', { inputTokens: 10_000, outputTokens: 2_000 });
console.log(`Cost: $${cost?.toFixed(4)}`);

Model Selector

import { listModels } from '@cogitator-ai/models';

function selectBestModel(options: {
  needsVision?: boolean;
  needsTools?: boolean;
  maxCost?: number;
  minContext?: number;
}): string | null {
  const models = listModels({
    supportsVision: options.needsVision,
    supportsTools: options.needsTools,
    maxPricePerMillion: options.maxCost,
    minContextWindow: options.minContext,
    excludeDeprecated: true,
  });

  if (models.length === 0) return null;

  models.sort((a, b) => {
    const aPrice = (a.pricing.input + a.pricing.output) / 2;
    const bPrice = (b.pricing.input + b.pricing.output) / 2;
    return aPrice - bPrice;
  });

  return models[0].id;
}

const cheapTool = selectBestModel({
  needsTools: true,
  maxCost: 2.0,
});

Provider Dashboard

import { getModelRegistry, initializeModels } from '@cogitator-ai/models';

async function showDashboard() {
  await initializeModels();
  const registry = getModelRegistry();

  console.log(`Total models: ${registry.getModelCount()}`);
  console.log();

  for (const provider of registry.listProviders()) {
    const models = registry.listModels({ provider: provider.id });
    console.log(`${provider.name}: ${models.length} models`);

    const avgPrice =
      models.reduce((sum, m) => sum + (m.pricing.input + m.pricing.output) / 2, 0) / models.length;
    console.log(`  Avg price: $${avgPrice.toFixed(2)}/M tokens`);
  }
}

Type Reference

import type {
  ModelInfo,
  ModelPricing,
  ModelCapabilities,
  ModelFilter,
  ProviderInfo,
  CacheOptions,
  RegistryOptions,
  LiteLLMModelEntry,
  LiteLLMModelData,
  TokenUsageForCost,
} from '@cogitator-ai/models';

import {
  ModelInfoSchema,
  ModelPricingSchema,
  ModelCapabilitiesSchema,
  ProviderInfoSchema,
} from '@cogitator-ai/models';

License

MIT