export const name = 'dsh-plugin-model-enhancer'; export const inject = ['webServer']; let cachedData = null; let lastFetchedAt = 0; const CACHE_TTL_MS = 3600 * 1000; // 1 hour async function getModelsDevData() { const now = Date.now(); if (cachedData && now - lastFetchedAt < CACHE_TTL_MS) { return cachedData; } try { const res = await fetch('https://models.dev/api.json', { headers: { 'User-Agent': 'DSH-Model-Enhancer/1.0.0' } }); if (!res.ok) { throw new Error(`Failed to fetch models.dev: HTTP ${res.status}`); } const json = await res.json(); cachedData = json; lastFetchedAt = now; return json; } catch (err) { if (cachedData) { // Fallback to stale cache if network fails return cachedData; } throw err; } } export function apply(ctx) { ctx.effect(() => { return ctx.webServer.register({ kind: 'exact', path: '/api/models-dev/models', handler: async (req, res) => { // Add CORS headers so web client can always reach it seamlessly res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); if (req.method === 'OPTIONS') { res.writeHead(204); res.end(); return; } if (req.method !== 'GET') { res.writeHead(405, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: 'Method Not Allowed' })); return; } try { const data = await getModelsDevData(); res.writeHead(200, { 'Content-Type': 'application/json', 'Cache-Control': 'public, max-age=3600' }); res.end(JSON.stringify(data)); } catch (err) { ctx.logger?.error?.('[model-enhancer] Error fetching models.dev:', err); res.writeHead(500, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: err.message || 'Internal Server Error' })); } } }); }, 'dsh-plugin-model-enhancer: webServer proxy route'); }