"use strict"; const http = require("http"); const https = require("https"); const fs = require("fs"); const net = require("net"); const crypto = require("crypto"); const PORT = Number(process.env.PORT || 7861); const GATEWAY_PORT = Number(process.env.API_SERVER_PORT || 8642); const DASHBOARD_PORT = Number(process.env.DASHBOARD_PORT || 9119); const TELEGRAM_WEBHOOK_PORT = Number(process.env.TELEGRAM_WEBHOOK_PORT || 8765); const JUPYTER_PORT = 8888; const GATEWAY_HOST = "127.0.0.1"; const TERMINAL_BASE = "/terminal"; const startTime = Date.now(); const API_SERVER_KEY = process.env.API_SERVER_KEY || ""; const APP_BASE = "/app"; const LOGIN_PATH = "/login"; const SESSION_COOKIE = "huggingmes_session"; // ── Private Space redirect support ── const SPACE_ID = (process.env.SPACE_ID || "").trim(); function deriveHfSpaceUrl() { if (SPACE_ID) return `https://huggingface.co/spaces/${SPACE_ID}`; const host = (process.env.SPACE_HOST || "").replace(/\.hf\.space$/i, ""); const author = (process.env.SPACE_AUTHOR_NAME || "").trim().toLowerCase(); if (author && host.toLowerCase().startsWith(author + "-")) { const spaceName = host.slice(author.length + 1); return `https://huggingface.co/spaces/${process.env.SPACE_AUTHOR_NAME}/${spaceName}`; } return ""; } const HF_SPACE_URL = deriveHfSpaceUrl(); // Privacy detection priority: // 1. SPACE_PRIVACY env var ("public"/"private") — explicit override, skip API call // 2. HF API auto-detect with retry // 3. Fail-secure: treat as private if SPACE_ID set const _spacPrivacyEnv = (process.env.SPACE_PRIVACY || "").trim().toLowerCase(); let SPACE_IS_PRIVATE; let _privacyDetectionDone = false; let _privacyDetectionResolve; const privacyDetectionReady = new Promise((res) => { _privacyDetectionResolve = res; }); if (_spacPrivacyEnv === "public") { SPACE_IS_PRIVATE = false; _privacyDetectionDone = true; console.log("[health-server] Space privacy: public (SPACE_PRIVACY env override)"); _privacyDetectionResolve(); } else if (_spacPrivacyEnv === "private") { SPACE_IS_PRIVATE = true; _privacyDetectionDone = true; console.log("[health-server] Space privacy: private (SPACE_PRIVACY env override)"); _privacyDetectionResolve(); } else { // Fail-secure default until API call resolves SPACE_IS_PRIVATE = !!SPACE_ID; } async function detectSpacePrivacy() { if (_spacPrivacyEnv === "public" || _spacPrivacyEnv === "private") return; if (!SPACE_ID) { SPACE_IS_PRIVATE = false; _privacyDetectionDone = true; _privacyDetectionResolve(); return; } const token = (process.env.HF_TOKEN || "").trim(); const reqOptions = { hostname: "huggingface.co", path: `/api/spaces/${SPACE_ID}`, method: "GET", headers: Object.assign( { "User-Agent": "HuggingMes/health-server" }, token ? { Authorization: `Bearer ${token}` } : {} ), }; const MAX_ATTEMPTS = 5; let detected = false; for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) { try { const result = await new Promise((resolve) => { const r = https.request(reqOptions, (apiRes) => { let body = ""; apiRes.on("data", (chunk) => { body += chunk; }); apiRes.on("end", () => { try { if (apiRes.statusCode === 200) { SPACE_IS_PRIVATE = JSON.parse(body).private === true; resolve({ ok: true }); } else if (apiRes.statusCode === 401 || apiRes.statusCode === 403) { SPACE_IS_PRIVATE = true; resolve({ ok: true }); } else { resolve({ ok: false }); } } catch { resolve({ ok: false }); } }); }); r.on("error", () => resolve({ ok: false })); r.setTimeout(8000, () => { r.destroy(); resolve({ ok: false }); }); r.end(); }); console.log(`[health-server] Privacy detection attempt ${attempt}/${MAX_ATTEMPTS}: ok=${result.ok}`); if (result.ok) { detected = true; break; } } catch {} const delay = Math.min(2000 * attempt, 10000); if (attempt < MAX_ATTEMPTS) await new Promise((r) => setTimeout(r, delay)); } if (!detected) { console.warn(`[health-server] Privacy detection failed after ${MAX_ATTEMPTS} attempts — defaulting to ${SPACE_IS_PRIVATE ? "private" : "public"}. TIP: Set SPACE_PRIVACY=public in Space secrets to skip API detection.`); } else { console.log(`[health-server] Space privacy detected: ${SPACE_IS_PRIVATE ? "private" : "public"}`); } _privacyDetectionDone = true; _privacyDetectionResolve(); } if (_spacPrivacyEnv !== "public" && _spacPrivacyEnv !== "private") { detectSpacePrivacy(); setInterval(detectSpacePrivacy, 5 * 60 * 1000); } const SYNC_STATUS_FILE = "/tmp/huggingmes-sync-status.json"; const CLOUDFLARE_KEEPALIVE_STATUS_FILE = "/tmp/huggingmes-cloudflare-keepalive-status.json"; function canConnect(port, host = GATEWAY_HOST, timeoutMs = 600) { return new Promise((resolve) => { const socket = net.createConnection({ port, host }); const done = (ok) => { socket.removeAllListeners(); socket.destroy(); resolve(ok); }; socket.setTimeout(timeoutMs); socket.once("connect", () => done(true)); socket.once("timeout", () => done(false)); socket.once("error", () => done(false)); }); } function readJson(path, fallback = null) { try { if (fs.existsSync(path)) return JSON.parse(fs.readFileSync(path, "utf8")); } catch {} return fallback; } function timingSafeEqualString(left, right) { if (!left || !right) return false; const leftBuffer = Buffer.from(left); const rightBuffer = Buffer.from(right); if (leftBuffer.length !== rightBuffer.length) return false; return crypto.timingSafeEqual(leftBuffer, rightBuffer); } function expectedSessionValue() { if (!API_SERVER_KEY) return ""; return crypto .createHmac("sha256", API_SERVER_KEY) .update("huggingmes-session-v1") .digest("hex"); } function parseCookies(req) { const header = req.headers.cookie || ""; const cookies = {}; for (const item of header.split(";")) { const separator = item.indexOf("="); if (separator < 0) continue; const name = item.slice(0, separator).trim(); const value = item.slice(separator + 1).trim(); if (!name) continue; try { cookies[name] = decodeURIComponent(value); } catch { cookies[name] = value; } } return cookies; } function isHttpsRequest(req) { return req.headers["x-forwarded-proto"] === "https"; } function buildSessionCookie(req) { const secure = isHttpsRequest(req) ? "; Secure" : ""; return `${SESSION_COOKIE}=${encodeURIComponent(expectedSessionValue())}; Path=/; HttpOnly; SameSite=Lax; Max-Age=86400${secure}`; } function getBearerToken(req) { const value = req.headers.authorization || ""; const match = /^Bearer\s+(.+)$/i.exec(value); return match ? match[1] : ""; } function isAuthorized(req) { if (!API_SERVER_KEY) return true; return ( timingSafeEqualString(getBearerToken(req), API_SERVER_KEY) || timingSafeEqualString( parseCookies(req)[SESSION_COOKIE], expectedSessionValue(), ) ); } function sanitizeNext(value) { if (!value || typeof value !== "string") return `${APP_BASE}/`; if (!value.startsWith("/") || value.startsWith("//")) return `${APP_BASE}/`; return value; } function loginUrl(nextPath) { return `${LOGIN_PATH}?next=${encodeURIComponent(sanitizeNext(nextPath))}`; } function renderLoginPage(nextPath, errorMessage = "") { const safeNext = sanitizeNext(nextPath); return ` HuggingMes

🪽 HuggingMes

Enter your GATEWAY_TOKEN to continue

${errorMessage ? `

Invalid token — try again

` : ""}
`; } function escapeHtml(value) { return String(value) .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """); } function readRequestBody(req, limit = 64 * 1024) { return new Promise((resolve, reject) => { let body = ""; req.on("data", (chunk) => { body += chunk; if (body.length > limit) { reject(new Error("Request body is too large.")); req.destroy(); } }); req.on("end", () => resolve(body)); req.on("error", reject); }); } function requireAuth(req, res) { if (isAuthorized(req)) return true; const parsed = new URL(req.url, "http://localhost"); redirect(res, loginUrl(`${parsed.pathname}${parsed.search}`)); return false; } function wantsHtml(req) { const accept = String(req.headers.accept || ""); return accept.includes("text/html"); } async function handleLogin(req, res, parsed) { const nextPath = sanitizeNext( parsed.searchParams.get("next") || `${APP_BASE}/`, ); if (!API_SERVER_KEY) { redirect(res, nextPath); return; } if (req.method === "GET") { res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", }); res.end(renderLoginPage(nextPath)); return; } if (req.method !== "POST") { res.writeHead(405, { allow: "GET, POST" }); res.end("Method not allowed"); return; } try { const body = await readRequestBody(req); const params = new URLSearchParams(body); const submittedToken = params.get("token") || ""; const submittedNext = sanitizeNext(params.get("next") || nextPath); if (!timingSafeEqualString(submittedToken, API_SERVER_KEY)) { res.writeHead(401, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", }); res.end( renderLoginPage( submittedNext, "That token did not match GATEWAY_TOKEN.", ), ); return; } res.writeHead(302, { location: submittedNext, "set-cookie": buildSessionCookie(req), "cache-control": "no-store", }); res.end(); } catch (error) { res.writeHead(400, { "content-type": "text/plain; charset=utf-8", "cache-control": "no-store", }); res.end(error.message || "Invalid login request."); } } function proxyRequest( req, res, targetPort, rewritePath = (path) => path, headerOverrides = {}, ) { const parsed = new URL(req.url, "http://localhost"); const targetPath = rewritePath(parsed.pathname) + parsed.search; const headers = { ...req.headers, ...headerOverrides, host: `${GATEWAY_HOST}:${targetPort}`, "x-forwarded-host": req.headers.host || "", "x-forwarded-proto": req.headers["x-forwarded-proto"] || "https", }; const proxy = http.request( { hostname: GATEWAY_HOST, port: targetPort, method: req.method, path: targetPath, headers, }, (upstream) => { res.writeHead(upstream.statusCode || 502, upstream.headers); upstream.pipe(res); }, ); proxy.on("error", (error) => { res.writeHead(502, { "content-type": "application/json" }); res.end(JSON.stringify({ error: "proxy_error", message: error.message })); }); req.pipe(proxy); } function redirect(res, location, statusCode = 302) { res.writeHead(statusCode, { location }); res.end(); } function formatUptime(ms) { const total = Math.floor(ms / 1000); const days = Math.floor(total / 86400); const hours = Math.floor((total % 86400) / 3600); const minutes = Math.floor((total % 3600) / 60); if (days) return `${days}d ${hours}h ${minutes}m`; if (hours) return `${hours}h ${minutes}m`; return `${minutes}m`; } async function statusPayload() { const gateway = await canConnect(GATEWAY_PORT); const dashboard = await canConnect(DASHBOARD_PORT); const telegramWebhook = !!process.env.TELEGRAM_WEBHOOK_URL && (await canConnect(TELEGRAM_WEBHOOK_PORT)); const sync = readJson( SYNC_STATUS_FILE, process.env.HF_TOKEN ? { status: "configured", message: "Backup is enabled; waiting for the first sync.", } : { status: "disabled", message: "HF_TOKEN is not configured." }, ); return { ok: gateway, uptime: formatUptime(Date.now() - startTime), startedAt: new Date(startTime).toISOString(), gateway, dashboard, authConfigured: !!API_SERVER_KEY, ports: { public: PORT, gateway: GATEWAY_PORT, dashboard: DASHBOARD_PORT, telegramWebhook: TELEGRAM_WEBHOOK_PORT, }, telegram: { configured: !!process.env.TELEGRAM_BOT_TOKEN, webhook: !!process.env.TELEGRAM_WEBHOOK_URL, webhookUrl: process.env.TELEGRAM_WEBHOOK_URL || "", webhookListening: telegramWebhook, proxy: process.env.CLOUDFLARE_PROXY_URL || "", }, model: process.env.MODEL_FOR_CONFIG || process.env.HERMES_MODEL || process.env.LLM_MODEL || "", provider: process.env.PROVIDER_FOR_CONFIG || process.env.HERMES_INFERENCE_PROVIDER || "auto", backup: sync, keepalive: readJson(CLOUDFLARE_KEEPALIVE_STATUS_FILE, null), }; } function renderPrivateRedirect(targetUrl) { const safeUrl = escapeHtml(targetUrl); return ` HuggingMes — Private Space

🔒 Private Space

This HuggingFace Space is private. You need to be logged in to huggingface.co to access it.

Redirecting you now…

Open on Hugging Face →
Redirecting in 3 seconds…
`; } function badge(label, state) { return `${escapeHtml(label)}`; } function toneBadge(label, tone = "neutral") { return `${escapeHtml(label)}`; } function valueOrUnset(value, fallback = "Not set") { return value ? escapeHtml(value) : `${escapeHtml(fallback)}`; } function renderTile({ title, value, detail = "", tone = "neutral", meta = "", }) { return `
${escapeHtml(title)}
${value}
${detail ? `
${detail}
` : ""} ${meta ? `
${meta}
` : ""}
`; } function renderDashboard(data) { const syncStatus = String(data.backup?.status || "unknown"); const syncTone = ["success", "restored", "synced", "configured"].includes( syncStatus, ) ? "ok" : syncStatus === "disabled" ? "warn" : "neutral"; const telegramTone = data.telegram.configured ? data.telegram.webhookListening || !data.telegram.webhook ? "ok" : "warn" : "warn"; const keepaliveConfigured = data.keepalive?.configured === true; const keepaliveStatus = String( data.keepalive?.status || (process.env.CLOUDFLARE_WORKERS_TOKEN ? "pending" : "not configured"), ); const keepAliveTone = keepaliveConfigured ? "ok" : process.env.CLOUDFLARE_WORKERS_TOKEN ? "warn" : "neutral"; const telegramDetail = data.telegram.configured ? `${data.telegram.webhook ? "Webhook" : "Polling"}${data.telegram.proxy ? " via CF proxy" : ""}` : "Not configured"; const backupDetail = data.backup?.message ? escapeHtml(data.backup.message) : "No status yet"; const keepAliveDetail = keepaliveConfigured ? `Pinging ${escapeHtml(data.keepalive.targetUrl || "/health")}` : keepaliveStatus === "error" && data.keepalive?.message ? escapeHtml(data.keepalive.message) : process.env.CLOUDFLARE_WORKERS_TOKEN ? "Worker pending or failed" : "Not configured"; const serviceOk = data.gateway && data.dashboard; const tiles = [ renderTile({ title: "Gateway", value: toneBadge( data.gateway ? "Online" : "Offline", data.gateway ? "ok" : "off", ), detail: data.gateway ? `API on port ${data.ports.gateway}` : `Unreachable`, tone: data.gateway ? "ok" : "off", meta: data.authConfigured ? "Protected" : "Unprotected", }), renderTile({ title: "Model", value: `${valueOrUnset(data.model)}`, detail: `Provider: ${valueOrUnset(data.provider || "auto")}`, tone: data.model ? "ok" : "warn", }), renderTile({ title: "Runtime", value: escapeHtml(data.uptime), detail: `Port ${data.ports.public}`, tone: "neutral", }), renderTile({ title: "Telegram", value: toneBadge( data.telegram.configured ? "Configured" : "Disabled", telegramTone, ), detail: telegramDetail, tone: telegramTone, }), renderTile({ title: "Backup", value: toneBadge(syncStatus.toUpperCase(), syncTone), detail: backupDetail, tone: syncTone, meta: data.backup?.timestamp ? `` : "", }), renderTile({ title: "Keep Awake", value: toneBadge( keepaliveConfigured ? "CF Cron" : keepaliveStatus.toUpperCase(), keepAliveTone, ), detail: keepAliveDetail, tone: keepAliveTone, }), ].join(""); return ` HuggingMes

HuggingMes

Self-hosted - Hermes Agent
Open Hermes Agent → 💻 Open Terminal → ⚙️ ENV Builder →
${tiles}
`; } const server = http.createServer(async (req, res) => { const parsed = new URL(req.url, "http://localhost"); const path = parsed.pathname; // Lightweight endpoint for client-side privacy fallback. // Called by dashboard JS to correct stale server-rendered SPACE_IS_PRIVATE value. // No auth required — not sensitive. if (path === "/api/is-private") { if (!_privacyDetectionDone) await privacyDetectionReady; res.writeHead(200, { "content-type": "application/json", "cache-control": "no-store" }); return res.end(JSON.stringify({ isPrivate: SPACE_IS_PRIVATE })); } if (path === LOGIN_PATH) { await handleLogin(req, res, parsed); return; } // ── Private Space Guard (server-side) ── // Intercepts browser HTML requests from raw .hf.space hosts when the Space is private. // /health and /status are always exempt so uptime monitors keep working. const isHtmlReq = (req.headers.accept || "").includes("text/html"); // RACE CONDITION FIX: await privacy detection before computing redirect logic. // Without this, the fail-secure default (SPACE_IS_PRIVATE=true when SPACE_ID is set) // causes public spaces to redirect during the brief window before API detection completes. if (isHtmlReq && !_privacyDetectionDone) { await Promise.race([ privacyDetectionReady, new Promise((r) => setTimeout(r, 1500)), ]); } // In-app navigation from same origin or HF App iframe — skip private redirect. const referer = req.headers.referer || req.headers.referrer || ""; const isSameOriginNav = !!(referer && typeof req.headers.host === "string" && referer.startsWith(`https://${req.headers.host}`)); const isFromHFApp = !!(referer && ( referer.startsWith("https://huggingface.co") || referer.startsWith("https://hf.co") )); const isDirectHfSpaceReq = SPACE_IS_PRIVATE && HF_SPACE_URL && isHtmlReq && !isSameOriginNav && !isFromHFApp && typeof req.headers.host === "string" && req.headers.host.endsWith(".hf.space"); if (path === "/hf-redirect" || path === "/hf-redirect/") { if (HF_SPACE_URL) { res.writeHead(302, { location: HF_SPACE_URL, "cache-control": "no-store" }); return res.end(); } res.writeHead(404, { "content-type": "text/plain" }); return res.end("SPACE_ID not configured."); } if (path === "/health" || path === `${APP_BASE}/health`) { const data = await statusPayload(); // Always 200 — health server up means the app is running. // Gateway readiness is in the JSON body (gateway: true/false). // Returning 503 here caused Docker HEALTHCHECK to fail during gateway // startup, keeping HF Space stuck in RUNNING_APP_STARTING indefinitely. res.writeHead(200, { "content-type": "application/json" }); res.end( JSON.stringify({ ok: data.ok, gateway: data.gateway, uptime: data.uptime, }), ); return; } if (path === "/status" || path === `${APP_BASE}/status`) { const data = await statusPayload(); res.writeHead(200, { "content-type": "application/json" }); res.end(JSON.stringify(data, null, 2)); return; } if (path === "/env-builder" || path === "/env-builder/") { if (!requireAuth(req, res)) return; try { const html = fs.readFileSync(require("path").join(__dirname, "env-builder.html"), "utf8"); res.writeHead(200, { "content-type": "text/html; charset=utf-8" }); res.end(html); } catch (e) { res.writeHead(404, { "content-type": "text/plain" }); res.end("env-builder.html not found"); } return; } if (path === "/env-builder.js") { if (!requireAuth(req, res)) return; try { const js = fs.readFileSync(require("path").join(__dirname, "env-builder.js"), "utf8"); res.writeHead(200, { "content-type": "application/javascript; charset=utf-8" }); res.end(js); } catch (e) { res.writeHead(404, { "content-type": "text/plain" }); res.end("env-builder.js not found"); } return; } if (path === "/") { if (isDirectHfSpaceReq) { res.writeHead(200, { "content-type": "text/html; charset=utf-8" }); return res.end(renderPrivateRedirect(HF_SPACE_URL)); } const data = await statusPayload(); res.writeHead(200, { "content-type": "text/html; charset=utf-8" }); res.end(renderDashboard(data)); return; } if (path === "/dashboard" || path === "/dashboard/") { redirect(res, `${APP_BASE}/${parsed.search}`); return; } if (path === "/telegram" || path.startsWith("/telegram/")) { proxyRequest(req, res, TELEGRAM_WEBHOOK_PORT); return; } if (path === APP_BASE || path.startsWith(`${APP_BASE}/`)) { if (!requireAuth(req, res)) return; proxyRequest( req, res, DASHBOARD_PORT, (p) => p.replace(/^\/app/, "") || "/", ); return; } if ( path === "/favicon.ico" || path.startsWith("/assets/") || path.startsWith("/api/") || path.startsWith("/dashboard-plugins/") || path.startsWith("/ds-assets/") ) { if (!requireAuth(req, res)) return; proxyRequest(req, res, DASHBOARD_PORT); return; } if ( [ "/analytics", "/chat", "/config", "/cron", "/docs", "/env", "/logs", "/models", "/plugins", "/profiles", "/sessions", "/skills", ].some((route) => path === route || path.startsWith(`${route}/`)) ) { redirect(res, `${APP_BASE}${path}${parsed.search}`); return; } if (path === "/v1" || path.startsWith("/v1/")) { if (!isAuthorized(req)) { if (wantsHtml(req)) { redirect(res, loginUrl(`${path}${parsed.search}`)); return; } res.writeHead(401, { "content-type": "application/json", "cache-control": "no-store", }); res.end( JSON.stringify({ error: "unauthorized", message: "Use Authorization: Bearer .", }), ); return; } const upstreamHeaders = getBearerToken(req) || !API_SERVER_KEY ? {} : { authorization: `Bearer ${API_SERVER_KEY}` }; proxyRequest(req, res, GATEWAY_PORT, (p) => p, upstreamHeaders); return; } if (path === TERMINAL_BASE || path.startsWith(`${TERMINAL_BASE}/`)) { if (!requireAuth(req, res)) return; canConnect(JUPYTER_PORT).then((up) => { if (!up) { res.writeHead(503, { "content-type": "text/plain; charset=utf-8" }); res.end("JupyterLab is not running. Set DEV_MODE=true and JUPYTER_TOKEN in Space secrets to enable /terminal/."); return; } // Inject the Jupyter token so JupyterLab skips its own login screen. // User already authenticated via GATEWAY_TOKEN — no second prompt needed. const jToken = process.env.JUPYTER_TOKEN || ""; const overrides = jToken ? { authorization: `token ${jToken}` } : {}; proxyRequest(req, res, JUPYTER_PORT, (p) => p, overrides); }); return; } res.writeHead(404, { "content-type": "text/plain; charset=utf-8" }); res.end("Not found"); }); // ── WebSocket upgrade (JupyterLab terminals + kernels need this) ── server.on("upgrade", (req, socket, head) => { const { pathname } = new URL(req.url, "http://localhost"); const isJupyter = pathname === TERMINAL_BASE || pathname.startsWith(`${TERMINAL_BASE}/`); const targetPort = isJupyter ? JUPYTER_PORT : GATEWAY_PORT; const ps = net.createConnection(targetPort, GATEWAY_HOST, () => { ps.write(`${req.method} ${req.url} HTTP/${req.httpVersion}\r\n`); ps.write(`Host: ${GATEWAY_HOST}:${targetPort}\r\n`); ps.write(`X-Forwarded-Host: ${req.headers.host || ""}\r\n`); ps.write("X-Forwarded-Proto: https\r\n"); for (let i = 0; i < req.rawHeaders.length; i += 2) { const lower = req.rawHeaders[i].toLowerCase(); if (["host", "x-forwarded-host", "x-forwarded-proto"].includes(lower)) continue; ps.write(`${req.rawHeaders[i]}: ${req.rawHeaders[i + 1]}\r\n`); } ps.write("\r\n"); if (head && head.length) ps.write(head); ps.pipe(socket).pipe(ps); }); ps.on("error", () => socket.destroy()); ps.on("close", () => socket.destroy()); socket.on("error", () => ps.destroy()); socket.on("close", () => ps.destroy()); }); server.timeout = 0; server.keepAliveTimeout = 65000; server.listen(PORT, "0.0.0.0", () => { console.log(`HuggingMes dashboard listening on 0.0.0.0:${PORT}`); });