UNPKG

@endlessblink/like-i-said-v2

Version:

Task Management & Memory for Claude - Track tasks, remember context, and maintain continuity across sessions with 27 powerful tools. Works with Claude Desktop and Claude Code.

265 lines (221 loc) 8.21 kB
/** * Automation Scheduler for Background Task Processing * Provides scheduled automation checks for proactive task status updates */ import { TaskAutomation } from './task-automation.js'; export class AutomationScheduler { constructor(taskStorage, automationConfig, fileSystemMonitor = null) { this.taskStorage = taskStorage; this.automationConfig = automationConfig; this.fileSystemMonitor = fileSystemMonitor; this.taskAutomation = new TaskAutomation(taskStorage); // Scheduling state this.intervalId = null; this.isRunning = false; this.lastRunTime = null; this.runCount = 0; // Performance tracking this.performanceStats = { totalRuns: 0, totalDuration: 0, averageDuration: 0, lastDuration: 0, automationsApplied: 0 }; } /** * Start the automation scheduler */ start() { if (this.isRunning) { console.error('⏰ Automation scheduler already running'); return; } if (!this.automationConfig.get('enableScheduledAutomation')) { console.error('⏰ Scheduled automation is disabled in configuration'); return; } const interval = this.automationConfig.get('automationInterval'); console.error(`⏰ Starting automation scheduler (interval: ${interval}ms)`); // Run initial check this.runAutomationCheck(); // Schedule periodic checks this.intervalId = setInterval(() => { this.runAutomationCheck(); }, interval); this.isRunning = true; } /** * Stop the automation scheduler */ stop() { if (!this.isRunning) { return; } if (this.intervalId) { clearInterval(this.intervalId); this.intervalId = null; } this.isRunning = false; console.error('⏰ Automation scheduler stopped'); } /** * Run automation check for all tasks */ async runAutomationCheck() { const startTime = Date.now(); console.error(`⏰ Running scheduled automation check #${this.runCount + 1}`); try { // Check if scheduled automation is still enabled if (!this.automationConfig.get('enableScheduledAutomation')) { console.error('⏰ Scheduled automation disabled, skipping check'); return; } // Get all tasks const tasks = this.taskStorage.getAllTasks(); let automationsApplied = 0; // Process tasks in batches to avoid overwhelming the system const batchSize = 10; for (let i = 0; i < tasks.length; i += batchSize) { const batch = tasks.slice(i, i + batchSize); // Process batch in parallel const results = await Promise.all( batch.map(task => this.checkTaskForAutomation(task)) ); // Count successful automations automationsApplied += results.filter(r => r).length; } // Update statistics const duration = Date.now() - startTime; this.updatePerformanceStats(duration, automationsApplied); console.error(`⏰ Automation check completed in ${duration}ms (${automationsApplied} automations applied)`); } catch (error) { console.error('❌ Error in scheduled automation check:', error); } finally { this.lastRunTime = new Date(); this.runCount++; } } /** * Check a single task for automation opportunities */ async checkTaskForAutomation(task) { try { // Skip if project is not enabled for automation if (!this.automationConfig.isProjectEnabled(task.project)) { return false; } // Skip if task is already completed if (task.status === 'done') { return false; } // Get automation suggestions const suggestions = await this.taskAutomation.getAutomationSuggestions(task.id); if (!suggestions || !suggestions.hasOpportunities) { return false; } // Check for high-confidence automations const confidenceThreshold = this.automationConfig.get('confidenceThreshold'); let applied = false; // Process status change suggestions if (suggestions.statusChange && suggestions.statusChange.confidence >= confidenceThreshold) { // For scheduled automation, only apply very high confidence changes if (suggestions.statusChange.confidence >= 0.85) { console.error(`⏰ Applying scheduled automation for task: ${task.title}`); if (this.fileSystemMonitor) { await this.fileSystemMonitor.applyStatusChange( task, suggestions.statusChange.suggestedStatus, suggestions.statusChange.reason ); applied = true; } } } // Process other high-confidence opportunities if (suggestions.opportunities) { for (const [type, opportunity] of Object.entries(suggestions.opportunities)) { if (opportunity.shouldApply && opportunity.confidence >= 0.9 && // Higher threshold for scheduled this.shouldApplyScheduledAutomation(type)) { console.error(`⏰ Scheduled automation opportunity: ${type} for ${task.title}`); if (this.fileSystemMonitor) { await this.fileSystemMonitor.applyAutomationType(task, type, opportunity); applied = true; } } } } return applied; } catch (error) { console.error(`❌ Error checking automation for task ${task.id}:`, error); return false; } } /** * Check if a specific automation type should be applied in scheduled mode */ shouldApplyScheduledAutomation(type) { // Only certain automation types are suitable for scheduled application const scheduledTypes = { 'subtask_completion': true, // Safe to apply automatically 'memory_evidence': false, // Requires more context 'dependency_resolution': true, // Safe when dependencies are clear 'stale_detection': true, // Good for scheduled checks 'blocked_detection': true // Good for scheduled checks }; return scheduledTypes[type] === true; } /** * Update performance statistics */ updatePerformanceStats(duration, automationsApplied) { this.performanceStats.totalRuns++; this.performanceStats.totalDuration += duration; this.performanceStats.averageDuration = this.performanceStats.totalDuration / this.performanceStats.totalRuns; this.performanceStats.lastDuration = duration; this.performanceStats.automationsApplied += automationsApplied; // Record in automation config this.automationConfig.recordAutomation('scheduledCheck', 'scheduler', { duration, automationsApplied, tasksChecked: this.taskStorage.getAllTasks().length }); } /** * Get scheduler status */ getStatus() { return { isRunning: this.isRunning, lastRunTime: this.lastRunTime, runCount: this.runCount, nextRunTime: this.getNextRunTime(), performanceStats: this.performanceStats, config: { enabled: this.automationConfig.get('enableScheduledAutomation'), interval: this.automationConfig.get('automationInterval') } }; } /** * Calculate next run time */ getNextRunTime() { if (!this.isRunning || !this.lastRunTime) { return null; } const interval = this.automationConfig.get('automationInterval'); return new Date(this.lastRunTime.getTime() + interval); } /** * Force an immediate automation check */ async forceCheck() { console.error('⏰ Forcing immediate automation check'); await this.runAutomationCheck(); } } export default AutomationScheduler;