How to Refresh Maka's Model Metadata Catalog: A Complete Guide

Refresh Maka's AI model metadata catalog by running npm run sync:model-metadata -- --refresh, which fetches the latest upstream data from models.dev, validates it, and regenerates the TypeScript source files.

Maka maintains a generated catalog of AI provider metadata and pricing data in its source tree. This catalog — stored in packages/core/src/model-metadata.generated.ts — must be periodically synchronized with the upstream models.dev API. The scripts/sync-model-metadata.mjs script automates this entire workflow, from fetching raw data to atomically replacing generated files.

Understanding the Model Metadata Refresh Architecture

The refresh pipeline in apache/maka is designed for safety, reproducibility, and auditability. All transformations are deterministic and version-controlled through a committed snapshot file.

Source and Generated Files

File Purpose
scripts/sync-model-metadata.mjs Core orchestration script
scripts/model-metadata/models-dev-api.snapshot.json Committed snapshot of upstream API response
packages/core/src/model-metadata.generated.ts Generated model metadata exports
packages/runtime/src/telemetry/model-pricing.generated.ts Generated pricing tables (optional)

Running a Standard Catalog Refresh

The standard workflow fetches live data from models.dev and regenerates all TypeScript sources.

Command Syntax

npm run sync:model-metadata -- --refresh

This executes the main() entry point in scripts/sync-model-metadata.mjs with the following stages:

  1. Fetch upstream data via readUpstream(SOURCE_URL)
  2. Project raw JSON into internal maps (buildProjection())
  3. Validate against shrinkage rules
  4. Write snapshot with SHA-256 digest
  5. Generate TypeScript modules with provenance headers
  6. Atomic file replacement via replaceFilesTransactionally()

Refresh Options and Flags

Refresh from Local File (Offline/CI Reproducibility)

Use --refresh-input to bypass live API calls and use a saved response:

npm run sync:model-metadata -- \
  --refresh \
  --refresh-input scripts/model-metadata/models-dev-api.snapshot.json

This pattern ensures CI builds remain deterministic even if models.dev is unavailable.

Accept Upstream Removals

By default, the refresh refuses to drop providers or models that existed in the previous snapshot. This guard prevents accidental data loss.

Override with --accept-upstream-removals when providers are legitimately discontinued:

npm run sync:model-metadata -- \
  --refresh \
  --accept-upstream-removals

The validation logic in sync-model-metadata.mjs implements this check:

if (!options.acceptUpstreamRemovals) {
  const previous = await loadSnapshotIfPresent(snapshotPath);
  if (previous) assertProjectionDoesNotShrink(previous.projection, projection);
}

Verify Without Writing (--check)

Validate that generated files match the committed snapshot without modifying any files:

npm run sync:model-metadata -- --check

Useful for pre-commit hooks or CI gates.

Programmatic Refresh Control

Import and invoke the refresh pipeline directly from Node.js:

import { main } from './scripts/sync-model-metadata.mjs';

// Standard refresh with file writes
await main(['node', 'sync-model-metadata.mjs', '--refresh']);

// Drift detection only (no writes)
const report = await main(['node', 'sync-model-metadata.mjs', '--drift']);
console.log(report);

The Projection Pipeline: How Raw Data Becomes TypeScript

The buildProjection() function in scripts/sync-model-metadata.mjs transforms the raw models.dev response into four structured maps:

  • metadata — per-provider model capabilities via toMetadata
  • pricing — token cost data via toPricing
  • providerFacts — static provider attributes
  • providerOverrides — SDK-specific runtime adjustments

These projections are then serialized with full provenance:

// Excerpt from generated file header
// Source: scripts/model-metadata/models-dev-api.snapshot.json
// SHA-256: abc123...
// Retrieved: 2024-01-15T09:23:17Z

Atomic File Replacement Guarantees

The replaceFilesTransactionally() function ensures the catalog is never in a partially-written state:

  1. Write all new content to temporary paths
  2. Create backups of existing files
  3. Rename temporaries to final paths only after all writes succeed
  4. Clean up backups on success, or restore on failure

This mechanism protects against corruption during interrupted refreshes.

Summary

  • Primary command: npm run sync:model-metadata -- --refresh refreshes Maka's model metadata catalog from the live models.dev API
  • Local testing: Use --refresh-input path/to/local.json for offline or reproducible refreshes
  • Safety guard: --accept-upstream-removals is required to drop previously-known providers or models
  • Verification: --check validates generated files without writing
  • Core files: scripts/sync-model-metadata.mjs drives the process; outputs land in packages/core/src/model-metadata.generated.ts
  • Atomic writes: The refresh uses transactional file replacement to prevent corruption

Frequently Asked Questions

What happens if the upstream API removes a provider I still need?

The refresh fails with an assertion error unless you pass --accept-upstream-removals. This prevents silent data loss when providers disappear from models.dev. If you need to retain a discontinued provider, you must fork the snapshot or maintain local overrides.

Can I refresh the catalog without internet access?

Yes. Save a copy of the models.dev response as JSON, then run:

npm run sync:model-metadata -- --refresh --refresh-input ./saved-response.json

This pattern is used in apache/maka CI to ensure reproducible builds.

How do I know which snapshot version generated my TypeScript files?

Each generated file includes a header comment with the snapshot's SHA-256 hash and retrieval timestamp. Compare this against scripts/model-metadata/models-dev-api.snapshot.json to verify provenance.

What is the difference between --check and --drift?

Both perform read-only validation. --check exits with error code if generated files differ from the snapshot, suitable for CI gates. --drift returns a detailed report object for programmatic consumption without modifying exit behavior.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →