/**
* Regenerate `catalog.json`: metadata from models.dev's `hyper` entry, membership and this
* deployment's prices from `GET /v1/models`.
*
* npm run regen write the catalog
* npm run regen -- --dry print it without writing
*
* Two requests, no probing. Models.dev carries what Hyper's endpoints only partly report
* (the reasoning effort levels the deployment takes, vision, limits), and `/v1/models`
* is authoritative for which models exist and what this key is billed.
*/
import { writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { CATALOG_SOURCE, fetchFacts, toCatalog } from "./catalog.js";
const CATALOG_PATH = join(dirname(fileURLToPath(import.meta.url)), "catalog.json");
async function main(): Promise<void> {
const facts = await fetchFacts();
facts.sort((a, b) => a.id.localeCompare(b.id));
for (const model of facts) {
process.stdout.write(
[
model.id,
model.reasoning ? model.levels.join(",") || "on" : "-",
model.vision ? "vision" : "text",
`${model.contextWindow}/${model.maxTokens}`,
`$${model.cost.input}/${model.cost.output}/${model.cost.cacheRead}`,
].join("\t") + "\n",
);
}
if (process.argv.includes("--dry")) return;
const catalog = { ...toCatalog(facts), source: CATALOG_SOURCE };
writeFileSync(CATALOG_PATH, `${JSON.stringify(catalog, null, "\t")}\n`);
process.stdout.write(`wrote ${CATALOG_PATH}: ${facts.length} models from ${CATALOG_SOURCE}\n`);
}
await main();