| 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 { } |
| } |
| 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 }; |
| } |
|
|