UNPKG

virtue-cli

Version:

Personal character development CLI tool for tracking virtues and philosophical alignment

161 lines 5.94 kB
import { log } from '@clack/prompts'; import { writeFileSync, readFileSync, existsSync, mkdirSync, readdirSync, unlinkSync } from 'fs'; import { join } from 'path'; import { homedir } from 'os'; export class DiscoverySessionManager { sessionsDir; constructor() { this.sessionsDir = join(homedir(), '.virtue-cli', 'discovery-sessions'); this.ensureSessionsDirectory(); } ensureSessionsDirectory() { if (!existsSync(this.sessionsDir)) { mkdirSync(this.sessionsDir, { recursive: true }); } } saveSession(session) { try { const sessionPath = join(this.sessionsDir, `${session.id}.json`); const sessionData = { ...session, lastSaved: new Date() }; writeFileSync(sessionPath, JSON.stringify(sessionData, null, 2)); } catch (error) { log.warning(`Failed to save discovery session: ${error}`); } } loadSession(sessionId) { try { const sessionPath = join(this.sessionsDir, `${sessionId}.json`); if (!existsSync(sessionPath)) { return null; } const sessionData = JSON.parse(readFileSync(sessionPath, 'utf-8')); return { ...sessionData, lastSaved: new Date(sessionData.lastSaved) }; } catch (error) { log.warning(`Failed to load discovery session: ${error}`); return null; } } listActiveSessions() { try { const sessionFiles = readdirSync(this.sessionsDir) .filter((file) => file.endsWith('.json')); return sessionFiles .map((file) => { try { const sessionData = JSON.parse(readFileSync(join(this.sessionsDir, file), 'utf-8')); return { ...sessionData, lastSaved: new Date(sessionData.lastSaved) }; } catch { return null; } }) .filter((session) => session && !session.isComplete) .sort((a, b) => b.lastSaved.getTime() - a.lastSaved.getTime()); } catch (error) { log.warning(`Failed to list discovery sessions: ${error}`); return []; } } deleteSession(sessionId) { try { const sessionPath = join(this.sessionsDir, `${sessionId}.json`); if (existsSync(sessionPath)) { unlinkSync(sessionPath); } } catch (error) { log.warning(`Failed to delete discovery session: ${error}`); } } calculateProgress(session) { const totalPhases = 3; const baseQuestions = 4; // Initial questions before AI discovery const maxAIQuestions = 21; // Maximum additional AI questions (25 total - 4 base) const totalQuestions = baseQuestions + maxAIQuestions; const completedQuestions = session.currentQuestionCount; const percentComplete = Math.min((completedQuestions / totalQuestions) * 100, 100); // Estimate remaining time based on average 2 minutes per question const remainingQuestions = Math.max(0, totalQuestions - completedQuestions); const estimatedTimeRemaining = remainingQuestions * 2; return { totalQuestions, completedQuestions, currentPhase: session.currentPhase, totalPhases, percentComplete: Math.round(percentComplete), estimatedTimeRemaining, canPause: !session.isComplete && completedQuestions > 0, canResume: !session.isComplete && completedQuestions > 0 }; } createSession(profileName) { const sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; return { id: sessionId, profileName, responses: [], currentPhase: 1, currentQuestionCount: 0, lastSaved: new Date(), isComplete: false }; } updateSession(session, newResponses, currentPhase, questionCount) { const updatedSession = { ...session, responses: [...session.responses, ...newResponses], currentPhase, currentQuestionCount: questionCount, lastSaved: new Date() }; this.saveSession(updatedSession); return updatedSession; } completeSession(session) { const completedSession = { ...session, isComplete: true, lastSaved: new Date() }; this.saveSession(completedSession); // Clean up completed sessions older than 30 days this.cleanupOldSessions(); } cleanupOldSessions() { try { const thirtyDaysAgo = new Date(); thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); const sessionFiles = readdirSync(this.sessionsDir) .filter((file) => file.endsWith('.json')); sessionFiles.forEach((file) => { try { const sessionPath = join(this.sessionsDir, file); const sessionData = JSON.parse(readFileSync(sessionPath, 'utf-8')); const lastSaved = new Date(sessionData.lastSaved); if (sessionData.isComplete && lastSaved < thirtyDaysAgo) { unlinkSync(sessionPath); } } catch { // Ignore errors for individual files } }); } catch { // Silently handle cleanup errors } } } //# sourceMappingURL=DiscoverySessionManager.js.map