import { NextRequest } from "next/server"; import { promises as fs } from "fs"; import os from "os"; import path from "path"; export const runtime = "nodejs"; async function resolveLogFilePath() { if (process.env.CHAT_LOG_PATH) return process.env.CHAT_LOG_PATH; const candidates = [ process.env.DATA_DIR, process.env.HF_HOME, process.env.HOME, "/tmp", os.tmpdir(), process.cwd(), ].filter(Boolean) as string[]; for (const dir of candidates) { const candidate = path.join(dir, "chat-logs.jsonl"); try { await fs.access(candidate); return candidate; } catch { // try next } } // Default location if not present yet return path.join(os.tmpdir(), "chat-logs.jsonl"); } const ADMIN_TOKEN = process.env.ADMIN_TOKEN || ""; function isAuthorized(req: NextRequest) { if (!ADMIN_TOKEN) return true; const tokenFromHeader = req.headers.get("x-admin-token") || ""; const auth = req.headers.get("authorization") || ""; const tokenFromBearer = auth.toLowerCase().startsWith("bearer ") ? auth.slice(7) : ""; const tokenFromQuery = req.nextUrl.searchParams.get("token") || ""; return tokenFromHeader === ADMIN_TOKEN || tokenFromBearer === ADMIN_TOKEN || tokenFromQuery === ADMIN_TOKEN; } function clampInt(v: number, min: number, max: number) { return Math.max(min, Math.min(max, v)); } export async function GET(req: NextRequest) { if (!isAuthorized(req)) { return new Response(JSON.stringify({ error: "Unauthorized" }), { status: 401, headers: { "Content-Type": "application/json" }, }); } const tailParam = req.nextUrl.searchParams.get("tail"); const rawParam = req.nextUrl.searchParams.get("raw"); const tail = clampInt(Number(tailParam ?? "100"), 1, 2000); const raw = rawParam === "1" || rawParam === "true"; try { const logFile = await resolveLogFilePath(); const file = await fs.readFile(logFile, "utf8"); const lines = file.split(/\r?\n/).filter(Boolean); const sliced = lines.slice(Math.max(0, lines.length - tail)); if (raw) { return new Response(sliced.join("\n"), { headers: { "Content-Type": "text/plain; charset=utf-8" }, }); } const parsed = sliced .map((l) => { try { return JSON.parse(l); } catch { return null; } }) .filter(Boolean); return new Response(JSON.stringify({ count: parsed.length, logs: parsed }), { headers: { "Content-Type": "application/json" }, }); } catch (error) { const message = error instanceof Error ? error.message : String(error); const status = message.includes("ENOENT") ? 404 : 500; return new Response(JSON.stringify({ error: "Failed to read logs", message }), { status, headers: { "Content-Type": "application/json" }, }); } }