import { Global } from "../global"import { Log } from "../util/log"import path from "path"import z from "zod"import { Installation } from "../installation"import { Flag } from "../flag/flag"import { lazy } from "@/util/lazy" // Try to import bundled snapshot (generated at build time)// Falls back to undefined in dev mode when snapshot doesn't exist/* @ts-ignore */ export namespace ModelsDev { const log = Log.create({ service: "models.dev" }) const filepath = path.join(Global.Path.cache, "models.json") export const Model = z.object({ id: z.string(), name: z.string(), family: z.string().optional(), release_date: z.string(), attachment: z.boolean(), reasoning: z.boolean(), temperature: z.boolean(), tool_call: z.boolean(), interleaved: z .union([ z.literal(true), z .object({ field: z.enum(["reasoning_content", "reasoning_details"]), }) .strict(), ]) .optional(), cost: z .object({ input: z.number(), output: z.number(), cache_read: z.number().optional(), cache_write: z.number().optional(), context_over_200k: z .object({ input: z.number(), output: z.number(), cache_read: z.number().optional(), cache_write: z.number().optional(), }) .optional(), }) .optional(), limit: z.object({ context: z.number(), input: z.number().optional(), output: z.number(), }), modalities: z .object({ input: z.array(z.enum(["text", "audio", "image", "video", "pdf"])), output: z.array(z.enum(["text", "audio", "image", "video", "pdf"])), }) .optional(), experimental: z.boolean().optional(), status: z.enum(["alpha", "beta", "deprecated"]).optional(), options: z.record(z.string(), z.any()), headers: z.record(z.string(), z.string()).optional(), provider: z.object({ npm: z.string() }).optional(), variants: z.record(z.string(), z.record(z.string(), z.any())).optional(), }) export type Model = z.infer<typeof Model> export const Provider = z.object({ api: z.string().optional(), name: z.string(), env: z.array(z.string()), id: z.string(), npm: z.string().optional(), models: z.record(z.string(), Model), }) export type Provider = z.infer<typeof Provider> function url() { return Flag.OPENSCIENCE_MODELS_URL || "https://models.dev" } function hasCurrentFrontier(data: Record<string, any> | undefined) { // A well-formed catalog with the major providers populated is good enough to // serve synchronously; actual freshness is guaranteed by the startup + hourly // refresh() below, which always refetches live from models.dev. We deliberately // do NOT hardcode specific frontier model ids here — they churn (a provider // renaming its flagship would wrongly reject an otherwise-current catalog and // pin stale data). Just require the catalog to be structurally valid. const modelCount = (p: string) => Object.keys((data?.[p]?.models as Record<string, unknown>) ?? {}).length return modelCount("anthropic") > 0 && modelCount("openai") > 0 } async function fetchLive() { return fetch(`${url()}/api.json`, { headers: { "User-Agent": Installation.USER_AGENT, }, signal: AbortSignal.timeout(10 * 1000), }) .then((x) => (x.ok ? x.text() : undefined)) .then((text) => (text ? (JSON.parse(text) as Record<string, unknown>) : undefined)) .catch((e) => { log.error("Failed to fetch models.dev", { error: e, }) }) } export const Data = lazy(async () => { const file = Bun.file(filepath) const result = await file.json().catch(() => {}) if (result && (Flag.OPENSCIENCE_DISABLE_MODELS_FETCH || hasCurrentFrontier(result))) return result // @ts-ignore const snapshot = await import("./models-snapshot") .then((m) => m.snapshot as Record<string, unknown>) .catch(() => undefined) if (snapshot && (Flag.OPENSCIENCE_DISABLE_MODELS_FETCH || hasCurrentFrontier(snapshot as Record<string, any>))) return snapshot if (Flag.OPENSCIENCE_DISABLE_MODELS_FETCH) return {} const live = await fetchLive() if (live) { await Bun.write(file, JSON.stringify(live)) return live } return result ?? snapshot ?? {} }) export async function get() { const result = await Data() return result as Record<string, Provider> } export async function refresh() { const file = Bun.file(filepath) const result = await fetchLive() if (result) { await Bun.write(file, JSON.stringify(result)) ModelsDev.Data.reset() } }} if (!Flag.OPENSCIENCE_DISABLE_MODELS_FETCH) { ModelsDev.refresh() setInterval( async () => { await ModelsDev.refresh() }, 60 * 1000 * 60, ).unref()}
import { Global } from "../global"
import { Log } from "../util/log"
import path from "path"
import z from "zod"
import { Installation } from "../installation"
import { Flag } from "../flag/flag"
import { lazy } from "@/util/lazy"
// Try to import bundled snapshot (generated at build time)
// Falls back to undefined in dev mode when snapshot doesn't exist
/* @ts-ignore */
export namespace ModelsDev {
const log = Log.create({ service: "models.dev" })
const filepath = path.join(Global.Path.cache, "models.json")
export const Model = z.object({
id: z.string(),
name: z.string(),
family: z.string().optional(),
release_date: z.string(),
attachment: z.boolean(),
reasoning: z.boolean(),
temperature: z.boolean(),
tool_call: z.boolean(),
interleaved: z
.union([
z.literal(true),
z
.object({
field: z.enum(["reasoning_content", "reasoning_details"]),
})
.strict(),
])
.optional(),
cost: z
.object({
input: z.number(),
output: z.number(),
cache_read: z.number().optional(),
cache_write: z.number().optional(),
context_over_200k: z
.object({
input: z.number(),
output: z.number(),
cache_read: z.number().optional(),
cache_write: z.number().optional(),
})
.optional(),
})
.optional(),
limit: z.object({
context: z.number(),
input: z.number().optional(),
output: z.number(),
}),
modalities: z
.object({
input: z.array(z.enum(["text", "audio", "image", "video", "pdf"])),
output: z.array(z.enum(["text", "audio", "image", "video", "pdf"])),
})
.optional(),
experimental: z.boolean().optional(),
status: z.enum(["alpha", "beta", "deprecated"]).optional(),
options: z.record(z.string(), z.any()),
headers: z.record(z.string(), z.string()).optional(),
provider: z.object({ npm: z.string() }).optional(),
variants: z.record(z.string(), z.record(z.string(), z.any())).optional(),
})
export type Model = z.infer<typeof Model>
export const Provider = z.object({
api: z.string().optional(),
name: z.string(),
env: z.array(z.string()),
id: z.string(),
npm: z.string().optional(),
models: z.record(z.string(), Model),
})
export type Provider = z.infer<typeof Provider>
function url() {
return Flag.OPENSCIENCE_MODELS_URL || "https://models.dev"
}
function hasCurrentFrontier(data: Record<string, any> | undefined) {
// A well-formed catalog with the major providers populated is good enough to
// serve synchronously; actual freshness is guaranteed by the startup + hourly
// refresh() below, which always refetches live from models.dev. We deliberately
// do NOT hardcode specific frontier model ids here — they churn (a provider
// renaming its flagship would wrongly reject an otherwise-current catalog and
// pin stale data). Just require the catalog to be structurally valid.
const modelCount = (p: string) => Object.keys((data?.[p]?.models as Record<string, unknown>) ?? {}).length
return modelCount("anthropic") > 0 && modelCount("openai") > 0
}
async function fetchLive() {
return fetch(`${url()}/api.json`, {
headers: {
"User-Agent": Installation.USER_AGENT,
},
signal: AbortSignal.timeout(10 * 1000),
})
.then((x) => (x.ok ? x.text() : undefined))
.then((text) => (text ? (JSON.parse(text) as Record<string, unknown>) : undefined))
.catch((e) => {
log.error("Failed to fetch models.dev", {
error: e,
})
})
}
export const Data = lazy(async () => {
const file = Bun.file(filepath)
const result = await file.json().catch(() => {})
if (result && (Flag.OPENSCIENCE_DISABLE_MODELS_FETCH || hasCurrentFrontier(result))) return result
// @ts-ignore
const snapshot = await import("./models-snapshot")
.then((m) => m.snapshot as Record<string, unknown>)
.catch(() => undefined)
if (snapshot && (Flag.OPENSCIENCE_DISABLE_MODELS_FETCH || hasCurrentFrontier(snapshot as Record<string, any>)))
return snapshot
if (Flag.OPENSCIENCE_DISABLE_MODELS_FETCH) return {}
const live = await fetchLive()
if (live) {
await Bun.write(file, JSON.stringify(live))
return live
}
return result ?? snapshot ?? {}
})
export async function get() {
const result = await Data()
return result as Record<string, Provider>
}
export async function refresh() {
const file = Bun.file(filepath)
const result = await fetchLive()
if (result) {
await Bun.write(file, JSON.stringify(result))
ModelsDev.Data.reset()
}
}
}
if (!Flag.OPENSCIENCE_DISABLE_MODELS_FETCH) {
ModelsDev.refresh()
setInterval(
async () => {
await ModelsDev.refresh()
},
60 * 1000 * 60,
).unref()
}