File size: 2,745 Bytes
101ebaa
 
 
 
 
49687c1
 
 
 
 
 
101ebaa
 
 
 
 
 
 
49687c1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101ebaa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49687c1
 
 
 
 
 
 
 
 
 
 
 
 
 
101ebaa
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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") {
        // Heuristic: treat small values as seconds
        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; // 1 hour

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 });
    }
}