|
|
import { NextResponse } from "next/server"; |
|
|
|
|
|
interface OpenRouterModel { |
|
|
id: string; |
|
|
name: string; |
|
|
created_at?: string | number; |
|
|
createdAt?: string | number; |
|
|
created?: string | number; |
|
|
released_at?: string | number; |
|
|
releasedAt?: string | number; |
|
|
release_date?: string | number; |
|
|
pricing: { |
|
|
prompt: string; |
|
|
completion: string; |
|
|
}; |
|
|
context_length: number; |
|
|
} |
|
|
|
|
|
function toTimestampMs(value: unknown): number { |
|
|
if (typeof value === "number") { |
|
|
|
|
|
return value > 1_000_000_000_000 ? value : value * 1000; |
|
|
} |
|
|
if (typeof value === "string") { |
|
|
const parsed = Date.parse(value); |
|
|
return Number.isFinite(parsed) ? parsed : 0; |
|
|
} |
|
|
return 0; |
|
|
} |
|
|
|
|
|
function getModelTimestampMs(model: OpenRouterModel): number { |
|
|
return Math.max( |
|
|
toTimestampMs(model.released_at), |
|
|
toTimestampMs(model.releasedAt), |
|
|
toTimestampMs(model.release_date), |
|
|
toTimestampMs(model.created_at), |
|
|
toTimestampMs(model.createdAt), |
|
|
toTimestampMs(model.created) |
|
|
); |
|
|
} |
|
|
|
|
|
let cachedModels: { id: string; name: string }[] | null = null; |
|
|
let cacheTimestamp: number = 0; |
|
|
const CACHE_DURATION = 1000 * 60 * 60; |
|
|
|
|
|
export async function GET() { |
|
|
try { |
|
|
const now = Date.now(); |
|
|
if (cachedModels && now - cacheTimestamp < CACHE_DURATION) { |
|
|
return NextResponse.json(cachedModels); |
|
|
} |
|
|
|
|
|
const response = await fetch("https://openrouter.ai/api/v1/models", { |
|
|
headers: { |
|
|
Accept: "application/json", |
|
|
}, |
|
|
next: { revalidate: 3600 }, |
|
|
}); |
|
|
|
|
|
if (!response.ok) { |
|
|
throw new Error(`OpenRouter API error: ${response.status}`); |
|
|
} |
|
|
|
|
|
const data = await response.json(); |
|
|
|
|
|
cachedModels = data.data |
|
|
.slice() |
|
|
.sort((a: OpenRouterModel, b: OpenRouterModel) => { |
|
|
const bt = getModelTimestampMs(b); |
|
|
const at = getModelTimestampMs(a); |
|
|
if (bt !== at) return bt - at; |
|
|
const an = (a.name || a.id).toLowerCase(); |
|
|
const bn = (b.name || b.id).toLowerCase(); |
|
|
return an.localeCompare(bn); |
|
|
}) |
|
|
.map((model: OpenRouterModel) => ({ |
|
|
id: model.id, |
|
|
name: model.name || model.id, |
|
|
})); |
|
|
|
|
|
cacheTimestamp = now; |
|
|
|
|
|
return NextResponse.json(cachedModels); |
|
|
} catch (error) { |
|
|
console.error("Error fetching OpenRouter models:", error); |
|
|
if (cachedModels) { |
|
|
return NextResponse.json(cachedModels); |
|
|
} |
|
|
return NextResponse.json([], { status: 500 }); |
|
|
} |
|
|
} |
|
|
|