- Centralized catalog and registry handling on `ModelSpec` and `buildModel`, resolving compatibility at model build time. - Removed runtime compatibility detectors and switched provider request flows to direct `model.compat` reads. - Added compat fields (`supportsReasoningParams`, `alwaysSendMaxTokens`, `strictResponsesPairing`, `whenThinking`). - Persisted explicit compatibility overrides through `compatConfig` in discovery and cache merge paths.
65 lines
2.5 KiB
TypeScript
65 lines
2.5 KiB
TypeScript
import { buildModel } from "./build";
|
|
import MODELS from "./models.json" with { type: "json" };
|
|
import type { Api, KnownProvider, Model, ModelSpec, Usage } from "./types";
|
|
|
|
/**
|
|
* Static bundled model registry loaded from `models.json`.
|
|
*
|
|
* This module intentionally exposes compile-time defaults only.
|
|
* It does not include runtime discovery, models.dev overlays, or on-disk cache state.
|
|
*
|
|
* For runtime-aware resolution, use `createModelManager()` / `resolveProviderModels()`.
|
|
*/
|
|
let modelRegistry: Map<string, Map<string, Model<Api>>> | undefined;
|
|
|
|
/** Build (once) and return the enriched bundled-model registry. Lazy: enrichment of ~12K models is deferred off module load. */
|
|
function getModelRegistry(): Map<string, Map<string, Model<Api>>> {
|
|
if (modelRegistry === undefined) {
|
|
modelRegistry = new Map();
|
|
for (const [provider, models] of Object.entries(MODELS)) {
|
|
const providerModels = new Map<string, Model<Api>>();
|
|
for (const [id, model] of Object.entries(models)) {
|
|
providerModels.set(id, buildModel(model as ModelSpec<Api>));
|
|
}
|
|
modelRegistry.set(provider, providerModels);
|
|
}
|
|
}
|
|
return modelRegistry;
|
|
}
|
|
|
|
export type GeneratedProvider = keyof typeof MODELS;
|
|
|
|
export function getBundledModel<TApi extends Api = Api>(provider: GeneratedProvider, modelId: string): Model<TApi> {
|
|
const providerModels = getModelRegistry().get(provider);
|
|
return providerModels?.get(modelId) as Model<TApi>;
|
|
}
|
|
|
|
export function getBundledProviders(): KnownProvider[] {
|
|
return Object.keys(MODELS) as KnownProvider[];
|
|
}
|
|
|
|
export function getBundledModels(provider: GeneratedProvider): Model<Api>[] {
|
|
const models = getModelRegistry().get(provider);
|
|
return models ? (Array.from(models.values()) as Model<Api>[]) : [];
|
|
}
|
|
|
|
export function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage): Usage["cost"] {
|
|
usage.cost.input = (model.cost.input / 1000000) * usage.input;
|
|
usage.cost.output = (model.cost.output / 1000000) * usage.output;
|
|
usage.cost.cacheRead = (model.cost.cacheRead / 1000000) * usage.cacheRead;
|
|
usage.cost.cacheWrite = (model.cost.cacheWrite / 1000000) * usage.cacheWrite;
|
|
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
return usage.cost;
|
|
}
|
|
/**
|
|
* Check if two models are equal by comparing both their id and provider.
|
|
* Returns false if either model is null or undefined.
|
|
*/
|
|
export function modelsAreEqual<TApi extends Api>(
|
|
a: Model<TApi> | null | undefined,
|
|
b: Model<TApi> | null | undefined,
|
|
): boolean {
|
|
if (!a || !b) return false;
|
|
return a.id === b.id && a.provider === b.provider;
|
|
}
|