From 445edf24610b0149b32586f22dd6257053f63675 Mon Sep 17 00:00:00 2001 From: audrzejq <31422031+audrzejq@users.noreply.github.com> Date: Tue, 3 Mar 2026 19:28:23 +0100 Subject: [PATCH] add cron --- packages/web/api/cron/monitor-chutes.ts | 38 +++++++++++++++++++++ packages/web/api/cron/monitor-openrouter.ts | 34 ++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 packages/web/api/cron/monitor-chutes.ts create mode 100644 packages/web/api/cron/monitor-openrouter.ts diff --git a/packages/web/api/cron/monitor-chutes.ts b/packages/web/api/cron/monitor-chutes.ts new file mode 100644 index 000000000..b20ee6bd0 --- /dev/null +++ b/packages/web/api/cron/monitor-chutes.ts @@ -0,0 +1,38 @@ +import { runMonitor, round6 } from '../../../monitor/index' + +export const config = { + maxDuration: 60, +} + +export default async function handler(req: Request) { + const authHeader = req.headers.get('authorization') + if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) { + return new Response('Unauthorized', { status: 401 }) + } + + try { + await runMonitor({ + name: 'Chutes', + title: '🛰 Chutes Models Update', + s3Key: 'chutes/snapshot.json', + async fetchModels() { + const headers: Record = {} + if (process.env.CHUTES_API_KEY) headers['Authorization'] = `Bearer ${process.env.CHUTES_API_KEY}` + + const res = await fetch('https://llm.chutes.ai/v1/models', { headers }) + if (!res.ok) throw new Error(`Chutes API error: ${res.status}`) + const data = await res.json() as { data: Array<{ id: string; pricing: { prompt: number; completion: number } }> } + + return data.data.map(m => ({ + id: m.id, + price_prompt: round6(m.pricing.prompt), + price_completion: round6(m.pricing.completion), + })) + }, + }) + return new Response('ok') + } catch (err) { + console.error(err) + return new Response('error', { status: 500 }) + } +} \ No newline at end of file diff --git a/packages/web/api/cron/monitor-openrouter.ts b/packages/web/api/cron/monitor-openrouter.ts new file mode 100644 index 000000000..800718c0b --- /dev/null +++ b/packages/web/api/cron/monitor-openrouter.ts @@ -0,0 +1,34 @@ +import { runMonitor, round6 } from '../../../monitor/index' + +export const config = { + maxDuration: 60, +} + +export default async function handler(req: Request) { + const authHeader = req.headers.get('authorization') + if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) { + return new Response('Unauthorized', { status: 401 }) + } + + try { + await runMonitor({ + name: 'OpenRouter', + title: '🛰 OpenRouter Models Update', + s3Key: 'openrouter/snapshot.json', + async fetchModels() { + const res = await fetch('https://openrouter.ai/api/v1/models') + if (!res.ok) throw new Error(`OpenRouter API error: ${res.status}`) + const data = await res.json() as { data: Array<{ id: string; pricing: { prompt: string; completion: string } }> } + return data.data.map(m => ({ + id: m.id, + price_prompt: round6(parseFloat(m.pricing.prompt) * 1_000_000), + price_completion: round6(parseFloat(m.pricing.completion) * 1_000_000), + })) + }, + }) + return new Response('ok') + } catch (err) { + console.error(err) + return new Response('error', { status: 500 }) + } +} \ No newline at end of file