io / artifacts /api-server /src /lib /feedback.ts
thagnitti's picture
cleanup: strip dead code (web-scraping, fine-tuning, scoring)
9b2f353 verified
import fs from "node:fs";
import path from "node:path";
import { logger } from "./logger";
const DATA_DIR = path.resolve(process.cwd(), "data");
const FEEDBACK_FILE = path.join(DATA_DIR, "feedback.jsonl");
export interface FeedbackEntry {
ts: number;
query: string;
rating: "up" | "down";
sources: string[];
answer?: string;
}
let totalUp = 0;
let totalDown = 0;
let loaded = false;
export function loadFeedback(): void {
if (loaded) return;
loaded = true;
try {
fs.mkdirSync(DATA_DIR, { recursive: true });
if (!fs.existsSync(FEEDBACK_FILE)) return;
const text = fs.readFileSync(FEEDBACK_FILE, "utf-8");
for (const line of text.split("\n")) {
if (!line.trim()) continue;
try {
const e = JSON.parse(line) as FeedbackEntry;
if (e.rating === "up") totalUp++;
else totalDown++;
} catch { /* skip malformed */ }
}
logger.info({ up: totalUp, down: totalDown }, "Feedback log loaded");
} catch (err) {
logger.warn({ err }, "Failed to load feedback log");
}
}
export function recordFeedback(
e: Omit<FeedbackEntry, "ts">,
): FeedbackEntry | null {
const entry: FeedbackEntry = { ts: Date.now(), ...e };
try {
fs.mkdirSync(DATA_DIR, { recursive: true });
fs.appendFileSync(FEEDBACK_FILE, JSON.stringify(entry) + "\n", "utf-8");
} catch (err) {
logger.error({ err }, "Failed to persist feedback");
return null;
}
if (entry.rating === "up") totalUp++;
else totalDown++;
return entry;
}
export function getStats() {
return { totalFeedback: totalUp + totalDown, totalUp, totalDown };
}