UNPKG

@phren/cli

Version:

Knowledge layer for AI agents - CLI, MCP server, and data layer

68 lines (67 loc) • 2.76 kB
/** * Session metrics tracking. * Extracted from hooks-session.ts for modularity. */ import * as fs from "fs"; import * as path from "path"; import { debugLog, errorMessage, withFileLock, getQualityMultiplier, recordFeedback, } from "./hooks-context.js"; import { sessionMetricsFile } from "../shared.js"; function parseSessionMetrics(phrenPathLocal) { const file = sessionMetricsFile(phrenPathLocal); if (!fs.existsSync(file)) return {}; try { return JSON.parse(fs.readFileSync(file, "utf8")); } catch (err) { debugLog(`parseSessionMetrics: failed to read ${file}: ${errorMessage(err)}`); return {}; } } function writeSessionMetrics(phrenPathLocal, data) { const file = sessionMetricsFile(phrenPathLocal); fs.mkdirSync(path.dirname(file), { recursive: true }); fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n"); } function updateSessionMetrics(phrenPathLocal, updater) { const file = sessionMetricsFile(phrenPathLocal); withFileLock(file, () => { const metrics = parseSessionMetrics(phrenPathLocal); updater(metrics); writeSessionMetrics(phrenPathLocal, metrics); }); } export function trackSessionMetrics(phrenPathLocal, sessionId, selected) { updateSessionMetrics(phrenPathLocal, (metrics) => { if (!metrics[sessionId]) metrics[sessionId] = { prompts: 0, keys: {}, lastChangedCount: 0, lastKeys: [] }; metrics[sessionId].prompts += 1; const injectedKeys = []; for (const injected of selected) { injectedKeys.push(injected.key); const key = injected.key; const seen = metrics[sessionId].keys[key] || 0; metrics[sessionId].keys[key] = seen + 1; if (seen >= 1) recordFeedback(phrenPathLocal, key, "reprompt"); } const relevantCount = selected.filter((s) => getQualityMultiplier(phrenPathLocal, s.key) > 0.5).length; const prevRelevant = metrics[sessionId].lastChangedCount || 0; const prevKeys = metrics[sessionId].lastKeys || []; if (relevantCount > prevRelevant) { for (const prevKey of prevKeys) { recordFeedback(phrenPathLocal, prevKey, "helpful"); } } metrics[sessionId].lastChangedCount = relevantCount; metrics[sessionId].lastKeys = injectedKeys; metrics[sessionId].lastSeen = new Date().toISOString(); const thirtyDaysAgo = Date.now() - 30 * 86400000; for (const sid of Object.keys(metrics)) { const seen = metrics[sid].lastSeen; if (seen && new Date(seen).getTime() < thirtyDaysAgo) { delete metrics[sid]; } } }); }