How to Refresh the Model Metadata Catalog in Apache Maka
Use npm run sync:model-metadata -- --refresh to fetch the latest models.dev API data, validate it against shrinkage rules, and regenerate the TypeScript catalog files atomically.
The Apache Maka project maintains a synchronized catalog of AI model metadata to ensure accurate provider information and pricing data across its core and runtime packages. This catalog lives in packages/core/src/model-metadata.generated.ts and is derived from the public models.dev API. Refreshing this catalog requires executing a specialized synchronization script that handles data projection, validation, and atomic file replacement.
Understanding the Model Metadata Architecture
Maka's catalog system relies on a snapshot-based workflow that bridges upstream API changes with version-controlled TypeScript source files. The scripts/sync-model-metadata.mjs driver orchestrates the entire pipeline, converting raw JSON from models.dev into four internal data structures: metadata, pricing, providerFacts, and providerOverrides.
The generated outputs include:
packages/core/src/model-metadata.generated.ts– ExportsGENERATED_MODELS_DEV_METADATAcontaining per-provider model definitionspackages/runtime/src/telemetry/model-pricing.generated.ts– ExportsGENERATED_MODEL_PRICESfor runtime cost calculationsscripts/model-metadata/models-dev-api.snapshot.json– The committed SHA-256 hashed snapshot used for reproducibility and drift detection
Executing a Standard Refresh
To update the catalog with the latest live upstream data, run the npm script with the refresh flag. This invokes the main() function in scripts/sync-model-metadata.mjs, which fetches data from the SOURCE_URL, projects it into internal maps, and writes new snapshot and TypeScript files.
npm run sync:model-metadata -- --refresh
This command executes six distinct phases: fetching upstream data via readUpstream(), projecting raw JSON through buildProjection(), validating against shrinkage with assertProjectionDoesNotShrink(), digesting the snapshot with SHA-256, generating TypeScript modules, and performing atomic file replacement via replaceFilesTransactionally().
Handling Edge Cases and Variations
Refreshing from a Local File
When testing changes or working offline, bypass the live API by providing a local JSON file that mimics the models.dev response structure using the --refresh-input flag.
npm run sync:model-metadata -- \
--refresh \
--refresh-input path/to/local/models-dev.json
Accepting Upstream Removals
By default, the refresh fails if any provider or model present in the previous snapshot disappears from the new data. This shrinkage protection prevents accidental data loss. To deliberately remove discontinued providers, pass the --accept-upstream-removals flag:
npm run sync:model-metadata -- \
--refresh \
--accept-upstream-removals
The validation logic checks if (!options.acceptUpstreamRemovals) before calling assertProjectionDoesNotShrink() against the previous projection loaded via loadSnapshotIfPresent().
Verification Without Writing
Use the --check flag to validate that existing generated files match the committed snapshot without fetching new data or writing files. This is ideal for CI pipelines ensuring repository consistency.
npm run sync:model-metadata -- --check
Alternatively, use --drift to report differences without failing or writing:
const report = await main(['node', 'sync-model-metadata.mjs', '--drift']);
Programmatic Integration
Import the main function directly from scripts/sync-model-metadata.mjs to refresh catalogs within Node.js applications or test suites.
import { main } from './scripts/sync-model-metadata.mjs';
// Full refresh with writes
await main(['node', 'sync-model-metadata.mjs', '--refresh']);
// Read-only drift detection
const driftReport = await main(['node', 'sync-model-metadata.mjs', '--drift']);
Critical Implementation Files
Understanding these source files helps debug refresh failures or extend functionality:
scripts/sync-model-metadata.mjs– Core driver implementingmain(),buildProjection(), andreplaceFilesTransactionally()packages/core/src/model-metadata.generated.ts– Generated TypeScript containingGENERATED_MODELS_DEV_METADATApackages/runtime/src/telemetry/model-pricing.generated.ts– Generated pricing constants used by telemetry systemsscripts/model-metadata/models-dev-api.snapshot.json– Version-controlled JSON snapshot with SHA-256 digest
Summary
- Refresh the model metadata catalog by running
npm run sync:model-metadata -- --refreshto fetch models.dev data and regenerate TypeScript sources - Prevent data loss through default shrinkage protection that rejects removals unless
--accept-upstream-removalsis specified - Test locally using
--refresh-inputwith a local JSON file to avoid hitting the live API - Validate consistency via
--checkfor CI workflows or--driftfor reporting - Atomic writes ensure
packages/core/src/model-metadata.generated.tsand related files are never partially updated
Frequently Asked Questions
Why does my refresh fail with a shrinkage error?
The refresh aborts when providers or models from the previous snapshot are missing in the new upstream data. This prevents accidental deletion of metadata. Run with --accept-upstream-removals only if you intentionally want to remove discontinued models from the catalog.
Can I refresh the catalog without internet access?
Yes. Save a local copy of the models.dev API response as JSON, then run npm run sync:model-metadata -- --refresh --refresh-input ./local-file.json. The script reads from this path instead of fetching SOURCE_URL, making it suitable for air-gapped environments or reproducible CI builds.
How do I verify the generated files match the repository state?
Execute npm run sync:model-metadata -- --check. This compares the current snapshot against the generated TypeScript files without fetching new data or writing to disk, returning a non-zero exit code if they differ. This ensures the committed generated files are synchronized with the snapshot.
What happens if the refresh is interrupted mid-process?
The replaceFilesTransactionally() function stages temporary copies and only swaps them after all writes succeed. If the process crashes during generation, the original model-metadata.generated.ts and snapshot files remain intact, preventing corruption or half-written states.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →