'use strict'; const express = require('express'); const { createProxyMiddleware } = require('http-proxy-middleware'); const fetch = require('node-fetch'); const app = express(); const GATEWAY_TOKEN = process.env.GATEWAY_TOKEN || 'changeme'; const LLAMA_URL = 'http://127.0.0.1:8080'; const PORT = 7860; const START_TIME = Date.now(); let proxiedCount = 0; // ── Helpers ─────────────────────────────────────────────────────────────────── function requireAuth(req, res, next) { const auth = req.headers['authorization'] || ''; const token = auth.replace('Bearer ', '').trim(); if (token !== GATEWAY_TOKEN) return res.status(401).json({ error: 'Unauthorized' }); next(); } function formatUptime(ms) { const s = Math.floor(ms / 1000); const m = Math.floor(s / 60); const h = Math.floor(m / 60); const d = Math.floor(h / 24); if (d > 0) return d + 'd ' + (h % 24) + 'h'; if (h > 0) return h + 'h ' + (m % 60) + 'm'; if (m > 0) return m + 'm ' + (s % 60) + 's'; return s + 's'; } // ── /health ─────────────────────────────────────────────────────────────────── app.get('/health', async (req, res) => { try { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 5000); const resp = await fetch(`${LLAMA_URL}/v1/models`, { headers: { 'Authorization': `Bearer ${GATEWAY_TOKEN}` }, signal: controller.signal }); clearTimeout(timeout); if (resp.ok) return res.status(200).json({ status: 'ok', llm: 'ready' }); return res.status(503).json({ status: 'degraded', code: resp.status }); } catch (e) { return res.status(503).json({ status: 'unavailable', error: e.message }); } }); // ── /stats (consumed by the dashboard and external monitors) ────────────────── app.get('/stats', async (req, res) => { let llmOnline = false; let modelId = process.env.MODEL_FILENAME || 'Unknown'; try { const ctrl = new AbortController(); const t = setTimeout(() => ctrl.abort(), 3000); const r = await fetch(`${LLAMA_URL}/v1/models`, { headers: { 'Authorization': `Bearer ${GATEWAY_TOKEN}` }, signal: ctrl.signal }); clearTimeout(t); if (r.ok) { llmOnline = true; const j = await r.json(); if (j.data && j.data[0] && j.data[0].id) modelId = j.data[0].id; } } catch (_) {} const bs = global.botState || {}; res.json({ llmOnline, modelId, contextLength: parseInt(process.env.CONTEXT_LENGTH || '2048'), threads: process.env.CPU_THREADS || 'auto', uptime: formatUptime(Date.now() - START_TIME), uptimeMs: Date.now() - START_TIME, proxiedCount, telegramConfigured: !!process.env.TELEGRAM_BOT_TOKEN, cfConfigured: !!(process.env.CLOUDFLARE_WORKERS_TOKEN && process.env.CLOUDFLARE_ACCOUNT_ID), proxyUrl: process.env.CLOUDFLARE_TELEGRAM_PROXY_URL || null, spaceUrl: process.env.SPACE_URL || null, backupEnabled: !!(process.env.HF_TOKEN && process.env.HF_BACKUP_DATASET), backupDataset: process.env.HF_BACKUP_DATASET || null, totalMessages: bs.totalMessages || 0, lastMessageAt: bs.lastMessageAt || null, activeChats: bs.activeChats || 0, }); }); // ── / (Dashboard) ───────────────────────────────────────────────────────────── const DASHBOARD_HTML = `