UNPKG

flashbacker

Version:

Claude Code state management with session continuity and AI personas

99 lines 4.23 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.shouldRunSessionAnalysis = shouldRunSessionAnalysis; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const conversation_logs_1 = require("../../utils/conversation-logs"); function getStatePath(projectDir) { return path_1.default.join(projectDir, '.claude', 'flashback', 'state', 'session-analysis.json'); } async function readLastRunState(projectDir) { try { const p = getStatePath(projectDir); const raw = await fs_extra_1.default.readFile(p, 'utf-8'); return JSON.parse(raw); } catch { return null; } } async function writeLastRunState(projectDir, state) { const p = getStatePath(projectDir); await fs_extra_1.default.ensureDir(path_1.default.dirname(p)); await fs_extra_1.default.writeFile(p, JSON.stringify(state, null, 2)); } async function countFileLines(filePath) { try { const content = await fs_extra_1.default.readFile(filePath, 'utf-8'); return content.split('\n').filter(Boolean).length; } catch { return 0; } } async function shouldRunSessionAnalysis(projectDir, opts = {}) { const { minMessages = 5, minElapsedMs = 30 * 60 * 1000, minBytesDelta = 4096, keywords = [] } = opts; const files = await (0, conversation_logs_1.getJSONLFiles)(projectDir); const latest = files[0]; const prev = files[1]; const now = Date.now(); const last = (await readLastRunState(projectDir)) || { lastRunAtMs: 0, files: {} }; let latestStats = { lines: 0, bytes: 0, mtimeMs: 0 }; let prevStats = { lines: 0, bytes: 0, mtimeMs: 0 }; if (latest) { const stat = await fs_extra_1.default.stat(latest.path); latestStats.bytes = stat.size; latestStats.mtimeMs = stat.mtimeMs; latestStats.lines = await countFileLines(latest.path); } if (prev) { const stat = await fs_extra_1.default.stat(prev.path); prevStats.bytes = stat.size; prevStats.mtimeMs = stat.mtimeMs; prevStats.lines = await countFileLines(prev.path); } const lastLatest = latest ? last.files[latest.path] : undefined; const bytesDelta = latest && lastLatest ? latestStats.bytes - lastLatest.bytes : latestStats.bytes; const newMessages = latest && lastLatest ? Math.max(0, latestStats.lines - lastLatest.lines) : latestStats.lines; const elapsed = now - (last.lastRunAtMs || 0); let keywordHit = false; if (keywords.length && latest) { try { const content = await fs_extra_1.default.readFile(latest.path, 'utf-8'); const tail = content.split('\n').slice(-Math.max(50, minMessages * 2)).join('\n'); keywordHit = keywords.some(k => new RegExp(k, 'i').test(tail)); } catch { } } const enoughMessages = newMessages >= minMessages; const enoughElapsed = elapsed >= minElapsedMs; const enoughBytes = bytesDelta >= minBytesDelta; const shouldRun = (enoughMessages && enoughElapsed) || keywordHit || (enoughBytes && enoughElapsed); const reason = shouldRun ? `run: newMsgs=${newMessages} bytesΔ=${bytesDelta} elapsedMs=${elapsed} keywordHit=${keywordHit}` : `skip: newMsgs=${newMessages} (<${minMessages}) bytesΔ=${bytesDelta} (<${minBytesDelta}) elapsedMs=${elapsed} (<${minElapsedMs}) keywordHit=${keywordHit}`; const updateState = async () => { const next = { lastRunAtMs: now, files: { ...(last.files || {}), ...(latest ? { [latest.path]: latestStats } : {}), ...(prev ? { [prev.path]: prevStats } : {}), }, }; await writeLastRunState(projectDir, next); }; const stats = { latest: latest?.path || null, prev: prev?.path || null, newMessages, bytesDelta, elapsedMs: elapsed, keywordHit, }; return { shouldRun, reason, stats, updateState }; } //# sourceMappingURL=significance.js.map