UNPKG

context-forge

Version:

AI orchestration platform with autonomous teams, enhancement planning, migration tools, 25+ slash commands, checkpoints & hooks. Multi-IDE: Claude, Cursor, Windsurf, Cline, Copilot

239 lines 8.84 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProgressTracker = void 0; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); class ProgressTracker { constructor(projectPath = process.cwd()) { this.currentEntry = null; this.progressFile = path_1.default.join(projectPath, '.context-forge', 'progress.json'); } async startOperation(command, operation, metadata) { const id = this.generateId(); this.currentEntry = { id, command, operation, status: 'in_progress', startTime: new Date(), projectPath: process.cwd(), metadata: metadata || {}, steps: [], }; await this.saveProgress(); return id; } async updateOperation(id, updates) { if (this.currentEntry && this.currentEntry.id === id) { Object.assign(this.currentEntry, updates); await this.saveProgress(); } else { // Update stored entry const progress = await this.loadProgress(); const entry = progress.find((p) => p.id === id); if (entry) { Object.assign(entry, updates); await this.saveToFile(progress); } } } async completeOperation(id, status = 'completed', metadata) { if (this.currentEntry && this.currentEntry.id === id) { this.currentEntry.status = status; this.currentEntry.endTime = new Date(); this.currentEntry.duration = this.currentEntry.endTime.getTime() - this.currentEntry.startTime.getTime(); if (metadata) { this.currentEntry.metadata = { ...this.currentEntry.metadata, ...metadata }; } await this.saveProgress(); this.currentEntry = null; } } async addStep(operationId, stepName, description) { const stepId = this.generateId(); const step = { id: stepId, name: stepName, status: 'in_progress', startTime: new Date(), description, }; if (this.currentEntry && this.currentEntry.id === operationId) { this.currentEntry.steps.push(step); await this.saveProgress(); } return stepId; } async completeStep(operationId, stepId, status = 'completed', metadata) { if (this.currentEntry && this.currentEntry.id === operationId) { const step = this.currentEntry.steps.find((s) => s.id === stepId); if (step) { step.status = status; step.endTime = new Date(); step.metadata = metadata; await this.saveProgress(); } } } async getProgress() { return await this.loadProgress(); } async getProgressSummary() { const progress = await this.loadProgress(); const now = new Date(); const recentActivity = progress .filter((p) => { const daysSinceStart = (now.getTime() - p.startTime.getTime()) / (1000 * 60 * 60 * 24); return daysSinceStart <= 7; // Last 7 days }) .sort((a, b) => b.startTime.getTime() - a.startTime.getTime()) .slice(0, 10); const totalOperations = progress.length; const completedOperations = progress.filter((p) => p.status === 'completed').length; const failedOperations = progress.filter((p) => p.status === 'failed').length; const inProgressOperations = progress.filter((p) => p.status === 'in_progress').length; const completedWithDuration = progress.filter((p) => p.status === 'completed' && p.duration); const averageDuration = completedWithDuration.length > 0 ? completedWithDuration.reduce((sum, p) => sum + (p.duration || 0), 0) / completedWithDuration.length : 0; const successRate = totalOperations > 0 ? (completedOperations / totalOperations) * 100 : 0; return { totalOperations, completedOperations, failedOperations, inProgressOperations, recentActivity, averageDuration, successRate, }; } async getCurrentOperation() { if (this.currentEntry) { return this.currentEntry; } const progress = await this.loadProgress(); return progress.find((p) => p.status === 'in_progress') || null; } async clearHistory(olderThanDays = 30) { const progress = await this.loadProgress(); const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - olderThanDays); const filtered = progress.filter((p) => { return p.startTime >= cutoffDate || p.status === 'in_progress'; }); const removedCount = progress.length - filtered.length; if (removedCount > 0) { await this.saveToFile(filtered); } return removedCount; } async loadProgress() { try { if (await fs_extra_1.default.pathExists(this.progressFile)) { const data = await fs_extra_1.default.readJson(this.progressFile); return Array.isArray(data) ? data.map(this.deserializeEntry) : []; } } catch (error) { console.warn('Failed to load progress file:', error); } return []; } async saveProgress() { if (!this.currentEntry) return; const progress = await this.loadProgress(); const existingIndex = progress.findIndex((p) => p.id === this.currentEntry.id); if (existingIndex >= 0) { progress[existingIndex] = this.currentEntry; } else { progress.push(this.currentEntry); } await this.saveToFile(progress); } async saveToFile(progress) { try { await fs_extra_1.default.ensureDir(path_1.default.dirname(this.progressFile)); await fs_extra_1.default.writeJson(this.progressFile, progress, { spaces: 2 }); } catch (error) { console.warn('Failed to save progress file:', error); } } deserializeEntry(data) { return { id: data.id, command: data.command, operation: data.operation, status: data.status, projectPath: data.projectPath, startTime: new Date(data.startTime), endTime: data.endTime ? new Date(data.endTime) : undefined, duration: data.duration, metadata: data.metadata, steps: data.steps?.map((step) => ({ id: step.id, name: step.name, status: step.status, startTime: step.startTime ? new Date(step.startTime) : undefined, endTime: step.endTime ? new Date(step.endTime) : undefined, description: step.description, metadata: step.metadata, })) || [], }; } generateId() { return Date.now().toString(36) + Math.random().toString(36).substr(2, 9); } // Utility methods for displaying progress formatDuration(milliseconds) { if (milliseconds < 1000) return `${milliseconds}ms`; if (milliseconds < 60000) return `${(milliseconds / 1000).toFixed(1)}s`; if (milliseconds < 3600000) return `${(milliseconds / 60000).toFixed(1)}m`; return `${(milliseconds / 3600000).toFixed(1)}h`; } getStatusIcon(status) { switch (status) { case 'completed': return '✅'; case 'failed': return '❌'; case 'in_progress': return '🔄'; case 'cancelled': return '⚠️'; case 'pending': return '⏳'; default: return '❓'; } } getStatusColor(status) { switch (status) { case 'completed': return 'green'; case 'failed': return 'red'; case 'in_progress': return 'yellow'; case 'cancelled': return 'orange'; case 'pending': return 'gray'; default: return 'white'; } } } exports.ProgressTracker = ProgressTracker; //# sourceMappingURL=progressTracker.js.map