import type { FastifyInstance } from 'fastify'; import type { Config } from '../config.js'; import type { ModelInfo } from '../types/api.js'; interface ApiModelsResponse { data?: ModelInfo[]; } const DEEPSEEK_STATIC_MODELS: ModelInfo[] = [ { id: 'deepseek-v4-flash', object: 'model', created: 0, owned_by: 'deepseek' }, { id: 'deepseek-v4-pro', object: 'model', created: 0, owned_by: 'deepseek' }, ]; export function registerModelRoutes(app: FastifyInstance, config: Config): void { app.get('/api/models', async (_req, reply) => { const models: ModelInfo[] = []; // 1. Fetch llama-swap models try { const res = await fetch(`${config.LLAMA_SWAP_URL}/v1/models`); if (res.ok) { const parsed = (await res.json()) as ApiModelsResponse; if (parsed.data) models.push(...parsed.data); } } catch { // llama-swap unreachable — proceed with whatever we have } // 2. If DeepSeek is configured, fetch live models from their API if (config.DEEPSEEK_API_KEY) { try { const baseURL = (config.DEEPSEEK_BASE_URL ?? 'https://api.deepseek.com').replace(/\/+$/, ''); const res = await fetch(`${baseURL}/v1/models`, { headers: { Authorization: `Bearer ${config.DEEPSEEK_API_KEY}` }, signal: AbortSignal.timeout(5_000), }); if (res.ok) { const parsed = (await res.json()) as ApiModelsResponse; if (parsed.data) models.push(...parsed.data); } else { // API call failed — fall back to static model list models.push(...DEEPSEEK_STATIC_MODELS); } } catch { // Network error — fall back to static model list models.push(...DEEPSEEK_STATIC_MODELS); } } if (models.length === 0) { reply.code(502); return { error: 'no models available from any provider' }; } return models; }); }