From 366d926f43df5ca98a5133a23d0c2ee4b64f6cf3 Mon Sep 17 00:00:00 2001 From: audrzejq <31422031+audrzejq@users.noreply.github.com> Date: Tue, 3 Mar 2026 19:47:27 +0100 Subject: [PATCH 1/5] remove api/cron from root --- api/cron/monitor-chutes.ts | 34 ---------------------------------- api/cron/monitor-openrouter.ts | 31 ------------------------------- 2 files changed, 65 deletions(-) delete mode 100644 api/cron/monitor-chutes.ts delete mode 100644 api/cron/monitor-openrouter.ts diff --git a/api/cron/monitor-chutes.ts b/api/cron/monitor-chutes.ts deleted file mode 100644 index e000da6b4..000000000 --- a/api/cron/monitor-chutes.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { runMonitor, round6 } from '@models.dev/monitor' - -export const config = { maxDuration: 60 } - -export default async function handler(req: Request) { - if (req.headers.get('authorization') !== `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(String(err), { status: 500 }) - } -} diff --git a/api/cron/monitor-openrouter.ts b/api/cron/monitor-openrouter.ts deleted file mode 100644 index 9cb370994..000000000 --- a/api/cron/monitor-openrouter.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { runMonitor, round6 } from '@models.dev/monitor' - -export const config = { maxDuration: 60 } - -export default async function handler(req: Request) { - if (req.headers.get('authorization') !== `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(String(err), { status: 500 }) - } -} From 1d95583669253591da6a7b106174457b977642b2 Mon Sep 17 00:00:00 2001 From: audrzejq <31422031+audrzejq@users.noreply.github.com> Date: Tue, 3 Mar 2026 19:48:16 +0100 Subject: [PATCH 2/5] Update vercel.json --- vercel.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/vercel.json b/vercel.json index 5727cf4fa..fcd4828f7 100644 --- a/vercel.json +++ b/vercel.json @@ -32,10 +32,6 @@ { "source": "/logos/:path*", "destination": "/logos/default.svg" - }, - { - "source": "/(.*)", - "destination": "/_index.html" } ] } \ No newline at end of file From 897c641f8e6f1211c9c5c0d9255f1df3e42c6c69 Mon Sep 17 00:00:00 2001 From: audrzejq <31422031+audrzejq@users.noreply.github.com> Date: Tue, 3 Mar 2026 19:55:41 +0100 Subject: [PATCH 3/5] fix deps --- {packages/web/api => api}/cron/monitor-chutes.ts | 0 {packages/web/api => api}/cron/monitor-openrouter.ts | 0 bun.lock | 1 + package.json | 3 ++- 4 files changed, 3 insertions(+), 1 deletion(-) rename {packages/web/api => api}/cron/monitor-chutes.ts (100%) rename {packages/web/api => api}/cron/monitor-openrouter.ts (100%) diff --git a/packages/web/api/cron/monitor-chutes.ts b/api/cron/monitor-chutes.ts similarity index 100% rename from packages/web/api/cron/monitor-chutes.ts rename to api/cron/monitor-chutes.ts diff --git a/packages/web/api/cron/monitor-openrouter.ts b/api/cron/monitor-openrouter.ts similarity index 100% rename from packages/web/api/cron/monitor-openrouter.ts rename to api/cron/monitor-openrouter.ts diff --git a/bun.lock b/bun.lock index e4d39e2cf..5a1e4763e 100644 --- a/bun.lock +++ b/bun.lock @@ -6,6 +6,7 @@ "name": "models.dev", "dependencies": { "@aws-sdk/client-s3": "^3.1000.0", + "@models.dev/monitor": "workspace:*", }, }, "packages/core": { diff --git a/package.json b/package.json index 7bab27fda..dfd3e0979 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ } }, "dependencies": { - "@aws-sdk/client-s3": "^3.1000.0" + "@aws-sdk/client-s3": "^3.1000.0", + "@models.dev/monitor": "workspace:*" } } \ No newline at end of file From 40fe90f5732b0df5c92241c51c1a9497ce86d6a9 Mon Sep 17 00:00:00 2001 From: audrzejq <31422031+audrzejq@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:02:46 +0100 Subject: [PATCH 4/5] fix this shyyyyt --- api/cron/monitor-chutes.ts | 2 +- api/cron/monitor-openrouter.ts | 2 +- vercel.json | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/api/cron/monitor-chutes.ts b/api/cron/monitor-chutes.ts index 6cd249c24..c172891ba 100644 --- a/api/cron/monitor-chutes.ts +++ b/api/cron/monitor-chutes.ts @@ -1,4 +1,4 @@ -import { runMonitor, round6 } from '@models.dev/monitor' +import { runMonitor, round6 } from '../../packages/monitor/index.ts' export const config = { maxDuration: 60, diff --git a/api/cron/monitor-openrouter.ts b/api/cron/monitor-openrouter.ts index 03dbc780a..cfc021670 100644 --- a/api/cron/monitor-openrouter.ts +++ b/api/cron/monitor-openrouter.ts @@ -1,4 +1,4 @@ -import { runMonitor, round6 } from '@models.dev/monitor' +import { runMonitor, round6 } from '../../packages/monitor/index.ts' export const config = { maxDuration: 60, diff --git a/vercel.json b/vercel.json index fcd4828f7..3f7b803e8 100644 --- a/vercel.json +++ b/vercel.json @@ -6,6 +6,11 @@ "installCommand": "bun install", "framework": null, "cleanUrls": false, + "functions": { + "api/cron/*.ts": { + "includeFiles": "packages/monitor/**" + } + }, "crons": [ { "path": "/api/cron/monitor-openrouter", From ea4a43827799ba86a7e7544d038b0f029a39a50f Mon Sep 17 00:00:00 2001 From: audrzejq <31422031+audrzejq@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:05:44 +0100 Subject: [PATCH 5/5] fix cron --- api/cron/monitor-chutes.ts | 16 ++++++++-------- api/cron/monitor-openrouter.ts | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/api/cron/monitor-chutes.ts b/api/cron/monitor-chutes.ts index c172891ba..26e3b375c 100644 --- a/api/cron/monitor-chutes.ts +++ b/api/cron/monitor-chutes.ts @@ -4,10 +4,10 @@ export const config = { maxDuration: 60, } -export default async function handler(req: Request) { - const authHeader = req.headers.get('authorization') +export default async function handler(req: any, res: any) { + const authHeader = req.headers['authorization'] if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) { - return new Response('Unauthorized', { status: 401 }) + return res.status(401).send('Unauthorized') } try { @@ -19,9 +19,9 @@ export default async function handler(req: Request) { 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 } }> } + const fetchRes = await fetch('https://llm.chutes.ai/v1/models', { headers }) + if (!fetchRes.ok) throw new Error(`Chutes API error: ${fetchRes.status}`) + const data = await fetchRes.json() as { data: Array<{ id: string; pricing: { prompt: number; completion: number } }> } return data.data.map(m => ({ id: m.id, @@ -30,9 +30,9 @@ export default async function handler(req: Request) { })) }, }) - return new Response('ok') + return res.send('ok') } catch (err) { console.error(err) - return new Response('error', { status: 500 }) + return res.status(500).send('error') } } \ No newline at end of file diff --git a/api/cron/monitor-openrouter.ts b/api/cron/monitor-openrouter.ts index cfc021670..f31de46b8 100644 --- a/api/cron/monitor-openrouter.ts +++ b/api/cron/monitor-openrouter.ts @@ -4,10 +4,10 @@ export const config = { maxDuration: 60, } -export default async function handler(req: Request) { - const authHeader = req.headers.get('authorization') +export default async function handler(req: any, res: any) { + const authHeader = req.headers['authorization'] if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) { - return new Response('Unauthorized', { status: 401 }) + return res.status(401).send('Unauthorized') } try { @@ -16,9 +16,9 @@ export default async function handler(req: Request) { 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 } }> } + const fetchRes = await fetch('https://openrouter.ai/api/v1/models') + if (!fetchRes.ok) throw new Error(`OpenRouter API error: ${fetchRes.status}`) + const data = await fetchRes.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), @@ -26,9 +26,9 @@ export default async function handler(req: Request) { })) }, }) - return new Response('ok') + return res.send('ok') } catch (err) { console.error(err) - return new Response('error', { status: 500 }) + return res.status(500).send('error') } } \ No newline at end of file