UNPKG

devibe

Version:

Intelligent repository cleanup with auto mode, AI learning, markdown consolidation, auto-consolidate workflow, context-aware classification, and cost optimization

246 lines 9.16 kB
/** * Markdown Consolidator * * Executes consolidation strategies on markdown files. */ import * as fs from 'fs/promises'; import * as path from 'path'; export class MarkdownConsolidator { aiAnalyzer; backupManager; constructor(aiAnalyzer, backupManager) { this.aiAnalyzer = aiAnalyzer; this.backupManager = backupManager; } /** * Create consolidation plans from files */ async createPlan(files, options) { const clusters = await this.aiAnalyzer.clusterByTopic(files); const plans = []; for (const cluster of clusters.slice(0, options.maxOutputFiles)) { if (cluster.consolidationStrategy === 'merge') { plans.push({ strategy: 'merge-by-topic', inputFiles: cluster.files, outputFile: cluster.suggestedFilename, preserveOriginals: options.preserveOriginals, confidence: 0.85, reasoning: `Merge ${cluster.files.length} files on topic: ${cluster.description}` }); } else if (cluster.consolidationStrategy === 'summarize') { plans.push({ strategy: 'summarize-cluster', inputFiles: cluster.files, outputFile: cluster.suggestedFilename, preserveOriginals: options.preserveOriginals, confidence: 0.90, reasoning: `Summarize ${cluster.files.length} similar files: ${cluster.description}` }); } } return plans; } /** * Execute a consolidation plan */ async executePlan(plan) { // Backup originals const backupEntries = []; for (const file of plan.inputFiles) { const entry = await this.backupManager.backupFile(file.path, 'modify'); backupEntries.push(entry); } // Create manifest for this consolidation const manifest = await this.backupManager.createManifest(backupEntries); let consolidatedContent; switch (plan.strategy) { case 'merge-by-topic': consolidatedContent = this.mergeByTopic(plan.inputFiles); break; case 'merge-by-folder': consolidatedContent = this.mergeByFolder(plan.inputFiles); break; case 'summarize-cluster': consolidatedContent = this.summarizeCluster(plan.inputFiles); break; default: throw new Error(`Unknown strategy: ${plan.strategy}`); } // Write consolidated file await fs.mkdir(path.dirname(plan.outputFile), { recursive: true }); await fs.writeFile(plan.outputFile, consolidatedContent); return { success: true, outputFile: plan.outputFile, inputFiles: plan.inputFiles.length, action: plan.strategy, backupPath: manifest.id }; } /** * Merge files by topic - combines full content */ mergeByTopic(files) { const sorted = files.sort((a, b) => b.metadata.wordCount - a.metadata.wordCount); const sections = []; // Header sections.push(`# ${this.inferTopicTitle(files)}`); sections.push(''); sections.push(`*Consolidated from ${files.length} files on ${new Date().toLocaleDateString()}*`); sections.push(''); sections.push('---'); sections.push(''); // Table of contents sections.push('## Table of Contents'); sections.push(''); for (const file of sorted) { sections.push(`- [${file.metadata.title}](#${this.slugify(file.metadata.title)})`); } sections.push(''); sections.push('---'); sections.push(''); // Content for (const file of sorted) { sections.push(`## ${file.metadata.title}`); sections.push(''); sections.push(`*Originally from: ${file.name}*`); sections.push(''); // Remove the file's own title if present let content = file.content.replace(/^#\s+.+$/m, '').trim(); sections.push(content); sections.push(''); sections.push('---'); sections.push(''); } // Source attribution sections.push('## Source Files'); sections.push(''); sections.push('This document was consolidated from:'); sections.push(''); for (const file of files) { sections.push(`- \`${file.relativePath}\` (${file.metadata.wordCount} words, modified ${file.lastModified.toLocaleDateString()})`); } return sections.join('\n'); } /** * Merge files by folder - creates index */ mergeByFolder(files) { const folder = path.dirname(files[0].relativePath); const sections = []; sections.push(`# ${path.basename(folder)} Documentation`); sections.push(''); sections.push(`*Index of ${files.length} documents*`); sections.push(''); sections.push('---'); sections.push(''); for (const file of files) { sections.push(`## [${file.metadata.title}](./${file.name})`); sections.push(''); // Extract first paragraph as preview const preview = this.extractPreview(file.content); if (preview) { sections.push(preview); sections.push(''); } if (file.metadata.headers.length > 0) { sections.push('**Contents:**'); for (const header of file.metadata.headers.slice(0, 5)) { sections.push(`- ${header}`); } sections.push(''); } } return sections.join('\n'); } /** * Summarize cluster - simple version (AI-powered would be better) */ summarizeCluster(files) { const sections = []; sections.push(`# Summary: ${this.inferTopicTitle(files)}`); sections.push(''); sections.push(`*Summary of ${files.length} documents*`); sections.push(''); sections.push('---'); sections.push(''); sections.push('## Overview'); sections.push(''); sections.push(`This document summarizes key information from ${files.length} related markdown files:`); sections.push(''); for (const file of files) { sections.push(`- **${file.metadata.title}**: ${this.extractPreview(file.content)}`); } sections.push(''); sections.push('---'); sections.push(''); sections.push('## Detailed Content'); sections.push(''); for (const file of files) { sections.push(`### ${file.metadata.title}`); sections.push(''); sections.push(`*Source: ${file.name}*`); sections.push(''); // Use first few paragraphs const paragraphs = file.content.split('\n\n').slice(0, 3); sections.push(paragraphs.join('\n\n')); sections.push(''); } return sections.join('\n'); } /** * Infer topic title from common words */ inferTopicTitle(files) { const words = files.map(f => f.metadata.title.toLowerCase().split(/\s+/)); const commonWords = this.findCommonWords(words); if (commonWords.length > 0) { return commonWords.map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' '); } return 'Consolidated Documentation'; } /** * Find common words across titles */ findCommonWords(wordArrays) { const wordCounts = new Map(); for (const words of wordArrays) { const uniqueWords = new Set(words); for (const word of uniqueWords) { if (word.length > 3) { wordCounts.set(word, (wordCounts.get(word) || 0) + 1); } } } const threshold = wordArrays.length / 2; return Array.from(wordCounts.entries()) .filter(([_, count]) => count >= threshold) .map(([word, _]) => word) .slice(0, 3); } /** * Slugify text for anchors */ slugify(text) { return text.toLowerCase().replace(/[^\w\s-]/g, '').replace(/\s+/g, '-'); } /** * Extract preview text from content */ extractPreview(content) { // Remove title const withoutTitle = content.replace(/^#\s+.+$/m, '').trim(); // Find first paragraph const paragraphs = withoutTitle.split('\n\n'); const firstPara = paragraphs.find(p => p.length > 20 && !p.startsWith('#') && !p.startsWith('-')); if (!firstPara) return ''; // Truncate if too long return firstPara.length > 200 ? firstPara.substring(0, 200) + '...' : firstPara; } } //# sourceMappingURL=markdown-consolidator.js.map