UNPKG

mcp-workflow-server-enhanced

Version:

Enhanced MCP Workflow Server with smart problem routing, comprehensive validation, guide compliance, and robust error handling. Intelligently routes to appropriate AI functions based on problem type.

527 lines (467 loc) 15.2 kB
import { TaskGenerationInputSchema, FunctionOutput, WorkflowContext, } from '../shared/types.js'; import { logWorkflowProgress } from '../shared/utils.js'; /** * Task Generation Function * * This function converts the detailed implementation plan into specific, * actionable tasks with clear instructions, acceptance criteria, and * implementation details for the execution phase. */ export function createTaskGenerationFunction() { return async (input: any, context: WorkflowContext): Promise<FunctionOutput> => { try { // Validate input const validatedInput = TaskGenerationInputSchema.parse(input); const { plan, granularity } = validatedInput; logWorkflowProgress(context, 'task-generation', 'Starting task generation from plan'); // Generate detailed tasks from the plan const tasks = await generateDetailedTasks(plan, granularity); // Create task execution order const executionOrder = determineExecutionOrder(tasks); // Generate task templates const taskTemplates = createTaskTemplates(tasks); // Create validation criteria const validationCriteria = createValidationCriteria(tasks); // Generate implementation guidelines const implementationGuidelines = generateImplementationGuidelines(plan, tasks); const result = { tasks, executionOrder, taskTemplates, validationCriteria, implementationGuidelines, taskSummary: generateTaskSummary(tasks), estimatedEffort: calculateTotalEffort(tasks), dependencies: mapTaskDependencies(tasks), qualityChecks: defineQualityChecks(tasks), }; logWorkflowProgress(context, 'task-generation', 'Task generation completed successfully'); return { success: true, result, nextStep: 'implementation', context, metadata: { totalTasks: tasks.length, granularity, estimatedDuration: result.estimatedEffort, processingTime: Date.now(), }, }; } catch (error) { return { success: false, result: { error: error.message, step: 'task-generation', }, context, }; } }; } /** * Generate detailed tasks from the implementation plan */ async function generateDetailedTasks( plan: any, granularity: 'high' | 'medium' | 'fine' ): Promise<Array<{ id: string; name: string; description: string; phase: string; priority: 'high' | 'medium' | 'low'; effort: string; dependencies: string[]; acceptanceCriteria: string[]; implementationSteps: string[]; deliverables: string[]; testingRequirements: string[]; qualityGates: string[]; }>> { const tasks = []; let taskId = 1; if (!plan?.implementationPlan?.phases) { throw new Error('Invalid plan structure: missing phases'); } for (const phase of plan.implementationPlan.phases) { for (const planTask of phase.tasks) { // Break down tasks based on granularity const detailedTasks = breakDownTask(planTask, phase.name, granularity); for (const task of detailedTasks) { tasks.push({ id: `TASK-${taskId.toString().padStart(3, '0')}`, name: task.name, description: task.description, phase: phase.name, priority: task.priority, effort: task.effort, dependencies: task.dependencies, acceptanceCriteria: generateAcceptanceCriteria(task), implementationSteps: generateImplementationSteps(task), deliverables: task.deliverables, testingRequirements: generateTestingRequirements(task), qualityGates: generateQualityGates(task), }); taskId++; } } } return tasks; } /** * Break down a plan task into detailed implementation tasks */ function breakDownTask( planTask: any, phaseName: string, granularity: 'high' | 'medium' | 'fine' ): Array<any> { const tasks = []; if (granularity === 'high') { // Keep tasks at high level tasks.push(planTask); } else if (granularity === 'medium') { // Break into 2-3 subtasks tasks.push(...breakIntoMediumTasks(planTask)); } else { // Break into fine-grained tasks tasks.push(...breakIntoFineTasks(planTask)); } return tasks; } /** * Break task into medium granularity */ function breakIntoMediumTasks(planTask: any): Array<any> { const tasks = []; const baseName = planTask.name; if (baseName.includes('Setup') || baseName.includes('Initialization')) { tasks.push({ ...planTask, name: `${baseName} - Configuration`, description: `Configure ${baseName.toLowerCase()} components and settings`, }); tasks.push({ ...planTask, name: `${baseName} - Validation`, description: `Validate ${baseName.toLowerCase()} setup and configuration`, }); } else if (baseName.includes('Development') || baseName.includes('Implementation')) { tasks.push({ ...planTask, name: `${baseName} - Core Logic`, description: `Implement core logic for ${baseName.toLowerCase()}`, }); tasks.push({ ...planTask, name: `${baseName} - Integration`, description: `Integrate ${baseName.toLowerCase()} with existing components`, }); } else if (baseName.includes('Testing')) { tasks.push({ ...planTask, name: `${baseName} - Test Implementation`, description: `Implement tests for ${baseName.toLowerCase()}`, }); tasks.push({ ...planTask, name: `${baseName} - Test Execution`, description: `Execute and validate ${baseName.toLowerCase()}`, }); } else { // Default breakdown tasks.push({ ...planTask, name: `${baseName} - Implementation`, description: `Implement ${baseName.toLowerCase()}`, }); tasks.push({ ...planTask, name: `${baseName} - Validation`, description: `Validate ${baseName.toLowerCase()}`, }); } return tasks; } /** * Break task into fine granularity */ function breakIntoFineTasks(planTask: any): Array<any> { const mediumTasks = breakIntoMediumTasks(planTask); const fineTasks = []; for (const mediumTask of mediumTasks) { fineTasks.push({ ...mediumTask, name: `${mediumTask.name} - Planning`, description: `Plan and design ${mediumTask.name.toLowerCase()}`, effort: '1-2 hours', }); fineTasks.push({ ...mediumTask, name: `${mediumTask.name} - Implementation`, description: `Implement ${mediumTask.name.toLowerCase()}`, effort: '2-4 hours', }); fineTasks.push({ ...mediumTask, name: `${mediumTask.name} - Testing`, description: `Test ${mediumTask.name.toLowerCase()}`, effort: '1-2 hours', }); } return fineTasks; } /** * Generate acceptance criteria for a task */ function generateAcceptanceCriteria(task: any): string[] { const criteria = []; criteria.push('Task implementation matches requirements'); criteria.push('Code follows established patterns and standards'); criteria.push('All deliverables are completed'); if (task.name.includes('Test')) { criteria.push('All tests pass successfully'); criteria.push('Test coverage meets minimum requirements'); } if (task.name.includes('Documentation')) { criteria.push('Documentation is comprehensive and accurate'); criteria.push('Examples and usage instructions are provided'); } if (task.name.includes('Integration')) { criteria.push('Integration points work correctly'); criteria.push('No breaking changes to existing functionality'); } return criteria; } /** * Generate implementation steps for a task */ function generateImplementationSteps(task: any): string[] { const steps = []; steps.push('Review task requirements and acceptance criteria'); steps.push('Plan implementation approach'); if (task.name.includes('Setup') || task.name.includes('Configuration')) { steps.push('Create configuration files'); steps.push('Install required dependencies'); steps.push('Validate configuration'); } else if (task.name.includes('Development') || task.name.includes('Implementation')) { steps.push('Implement core functionality'); steps.push('Add error handling and validation'); steps.push('Integrate with existing components'); } else if (task.name.includes('Testing')) { steps.push('Write test cases'); steps.push('Implement test code'); steps.push('Execute tests and validate results'); } else if (task.name.includes('Documentation')) { steps.push('Create documentation structure'); steps.push('Write comprehensive documentation'); steps.push('Add examples and usage instructions'); } steps.push('Review implementation against acceptance criteria'); steps.push('Perform quality checks'); steps.push('Mark task as complete'); return steps; } /** * Generate testing requirements for a task */ function generateTestingRequirements(task: any): string[] { const requirements = []; if (task.name.includes('Test')) { requirements.push('Implement comprehensive test suite'); requirements.push('Achieve minimum test coverage'); requirements.push('Include edge case testing'); } else { requirements.push('Unit tests for new functionality'); requirements.push('Integration tests where applicable'); requirements.push('Manual testing of deliverables'); } return requirements; } /** * Generate quality gates for a task */ function generateQualityGates(task: any): string[] { return [ 'Code review completed', 'All tests passing', 'Quality standards met', 'Documentation updated', 'Acceptance criteria satisfied', ]; } /** * Determine execution order for tasks */ function determineExecutionOrder(tasks: any[]): Array<{ taskId: string; order: number; parallelGroup?: number }> { const executionOrder = []; let currentOrder = 1; let parallelGroup = 1; // Group tasks by phase const tasksByPhase = tasks.reduce((groups, task) => { if (!groups[task.phase]) groups[task.phase] = []; groups[task.phase].push(task); return groups; }, {}); // Order tasks within each phase for (const [phase, phaseTasks] of Object.entries(tasksByPhase)) { const sortedTasks = (phaseTasks as any[]).sort((a, b) => { // High priority first if (a.priority === 'high' && b.priority !== 'high') return -1; if (b.priority === 'high' && a.priority !== 'high') return 1; // Then by dependencies if (a.dependencies.length === 0 && b.dependencies.length > 0) return -1; if (b.dependencies.length === 0 && a.dependencies.length > 0) return 1; return 0; }); for (const task of sortedTasks) { executionOrder.push({ taskId: task.id, order: currentOrder++, parallelGroup: task.dependencies.length === 0 ? parallelGroup : undefined, }); } parallelGroup++; } return executionOrder; } /** * Create task templates for common patterns */ function createTaskTemplates(tasks: any[]): { [key: string]: any } { return { setup: { steps: ['Plan', 'Configure', 'Validate'], checklist: ['Dependencies installed', 'Configuration verified', 'Setup tested'], }, development: { steps: ['Design', 'Implement', 'Test', 'Review'], checklist: ['Code implemented', 'Tests written', 'Code reviewed', 'Quality gates passed'], }, testing: { steps: ['Plan tests', 'Write tests', 'Execute tests', 'Validate results'], checklist: ['Test cases defined', 'Tests implemented', 'All tests pass', 'Coverage adequate'], }, documentation: { steps: ['Plan structure', 'Write content', 'Add examples', 'Review'], checklist: ['Structure defined', 'Content complete', 'Examples added', 'Review completed'], }, }; } /** * Create validation criteria for task completion */ function createValidationCriteria(tasks: any[]): { [key: string]: string[] } { const criteria = {}; for (const task of tasks) { criteria[task.id] = [ 'All acceptance criteria met', 'Implementation follows standards', 'Quality gates passed', 'Deliverables completed', 'Testing requirements satisfied', ]; } return criteria; } /** * Generate implementation guidelines */ function generateImplementationGuidelines(plan: any, tasks: any[]): { general: string[]; codeStandards: string[]; testingGuidelines: string[]; qualityRequirements: string[]; } { return { general: [ 'Follow the established project structure', 'Implement tasks in the specified order', 'Validate each task before proceeding', 'Document any deviations or issues', ], codeStandards: [ 'Use TypeScript for type safety', 'Follow ESLint and Prettier configurations', 'Write clear, self-documenting code', 'Include appropriate error handling', ], testingGuidelines: [ 'Write tests before or alongside implementation', 'Aim for high test coverage', 'Include both positive and negative test cases', 'Test edge cases and error conditions', ], qualityRequirements: [ 'All code must pass linting checks', 'No TypeScript errors allowed', 'All tests must pass', 'Code review required for all changes', ], }; } /** * Generate task summary */ function generateTaskSummary(tasks: any[]): { totalTasks: number; tasksByPhase: { [key: string]: number }; tasksByPriority: { [key: string]: number }; estimatedDuration: string; } { const tasksByPhase = tasks.reduce((counts, task) => { counts[task.phase] = (counts[task.phase] || 0) + 1; return counts; }, {}); const tasksByPriority = tasks.reduce((counts, task) => { counts[task.priority] = (counts[task.priority] || 0) + 1; return counts; }, {}); return { totalTasks: tasks.length, tasksByPhase, tasksByPriority, estimatedDuration: `${Math.ceil(tasks.length * 0.5)} to ${Math.ceil(tasks.length * 0.8)} days`, }; } /** * Calculate total effort for all tasks */ function calculateTotalEffort(tasks: any[]): string { const totalHours = tasks.length * 4; // Average 4 hours per task const days = Math.ceil(totalHours / 8); return `${totalHours} hours (approximately ${days} days)`; } /** * Map task dependencies */ function mapTaskDependencies(tasks: any[]): Array<{ taskId: string; dependsOn: string[] }> { return tasks .filter(task => task.dependencies.length > 0) .map(task => ({ taskId: task.id, dependsOn: task.dependencies, })); } /** * Define quality checks for tasks */ function defineQualityChecks(tasks: any[]): { [key: string]: string[] } { const checks = {}; for (const task of tasks) { checks[task.id] = [ 'Code compiles without errors', 'All tests pass', 'Linting checks pass', 'Code review approved', 'Documentation updated', ]; } return checks; }