UNPKG

virtue-cli

Version:

Personal character development CLI tool for tracking virtues and philosophical alignment

132 lines 5.61 kB
import { ExportManager } from './ExportManager.js'; import { writeFileSync, mkdirSync, existsSync } from 'fs'; import { join, resolve } from 'path'; import { formatDate } from '../utils/helpers.js'; import { log } from '@clack/prompts'; export class AutoSaveManager { db; exportManager; constructor(db) { this.db = db; this.exportManager = new ExportManager(db); } async saveDailyEntry(profile, entry) { if (!profile.output_directory) { return; // Auto-save not configured } try { const outputDir = resolve(profile.output_directory); this.ensureDirectoryExists(outputDir); // Create subdirectory for daily entries const dailyDir = join(outputDir, 'daily'); this.ensureDirectoryExists(dailyDir); // Generate filename: YYYY-MM-DD-daily.md const filename = `${entry.date}-daily.md`; const filepath = join(dailyDir, filename); // Generate markdown content for this specific entry const content = await this.generateDailyEntryMarkdown(profile, entry); writeFileSync(filepath, content); log.success(`Daily entry saved to: ${filepath}`); } catch (error) { log.error(`Failed to auto-save daily entry: ${error}`); } } async saveMonthlyDeepDive(profile, month, analysisData) { if (!profile.output_directory) { return; // Auto-save not configured } try { const outputDir = resolve(profile.output_directory); this.ensureDirectoryExists(outputDir); // Create subdirectory for monthly entries const monthlyDir = join(outputDir, 'monthly'); this.ensureDirectoryExists(monthlyDir); // Generate filename: YYYY-MM-monthly.md const filename = `${month}-monthly.md`; const filepath = join(monthlyDir, filename); // Generate markdown content for the monthly analysis const content = await this.generateMonthlyMarkdown(profile, month, analysisData); writeFileSync(filepath, content); log.success(`Monthly deep-dive saved to: ${filepath}`); } catch (error) { log.error(`Failed to auto-save monthly deep-dive: ${error}`); } } ensureDirectoryExists(dirPath) { if (!existsSync(dirPath)) { mkdirSync(dirPath, { recursive: true }); } } async generateDailyEntryMarkdown(profile, entry) { const virtues = this.db.getVirtuesForProfile(profile.id); const scores = JSON.parse(entry.virtue_scores); let content = `# Daily Virtue Check-in\n\n`; content += `**Date:** ${formatDate(new Date(entry.date))}\n`; content += `**Profile:** ${profile.name}\n`; content += `**Overall Coherence:** ${(entry.coherence_score * 100).toFixed(1)}%\n\n`; content += `## Virtue Scores\n\n`; for (const virtue of virtues) { const score = scores[virtue.id]; if (score) { const alignment = this.calculateAlignment(score.want, score.pull); content += `### ${virtue.emoji} ${virtue.name}\n`; content += `- **Want:** ${score.want}/10\n`; content += `- **Pull:** ${score.pull}/10\n`; content += `- **Alignment:** ${(alignment * 100).toFixed(1)}%\n\n`; } } if (entry.notes) { content += `## Notes\n\n${entry.notes}\n\n`; } content += `---\n`; content += `*Generated by Virtue CLI on ${new Date().toLocaleString()}*\n`; return content; } async generateMonthlyMarkdown(profile, month, analysisData) { let content = `# Monthly Deep-Dive Analysis\n\n`; content += `**Month:** ${month}\n`; content += `**Profile:** ${profile.name}\n`; content += `**Generated:** ${new Date().toLocaleString()}\n\n`; if (analysisData.insights) { content += `## Key Insights\n\n`; for (const insight of (analysisData.insights || [])) { content += `- ${insight}\n`; } content += `\n`; } if (analysisData.virtueAnalysis) { content += `## Virtue Analysis\n\n`; for (const [virtueId, analysis] of Object.entries(analysisData.virtueAnalysis)) { const virtue = this.db.getVirtue(virtueId); if (virtue && analysis) { content += `### ${virtue.emoji} ${virtue.name}\n`; content += `${analysis}\n\n`; } } } if (analysisData.recommendations) { content += `## Recommendations\n\n`; for (const rec of (analysisData.recommendations || [])) { content += `- ${rec}\n`; } content += `\n`; } if (analysisData.interventionPlan) { content += `## Intervention Plan\n\n`; content += `${analysisData.interventionPlan}\n\n`; } content += `---\n`; content += `*Generated by Virtue CLI on ${new Date().toLocaleString()}*\n`; return content; } calculateAlignment(want, pull) { if (want === 0 && pull === 0) return 1; const maxPossibleDifference = 10; const actualDifference = Math.abs(want - pull); return 1 - (actualDifference / maxPossibleDifference); } } //# sourceMappingURL=AutoSaveManager.js.map