UNPKG

@jmkim85/dev-flow-mcp

Version:

MCP-based Dev Flow - AI-powered development workflow management with 13 essential tools for TDD and context management

495 lines (445 loc) โ€ข 15.8 kB
/** * Project Tool Handlers Module * Implements project management MCP tool handlers for Dev Flow */ import { promises as fs } from 'fs'; import { join, basename } from 'path'; import { templateManager, PROJECT_ROOT, stateManager, simpleWorkflowManager } from './globals.js'; import { cleanTempFiles } from './clean-temp.js'; import { getVersion } from './version-manager.js'; // Project management tool handler implementations export async function cleanTempFilesTool() { try { const result = await cleanTempFiles(); return { content: [{ type: "text", text: `๐Ÿงน **Temporary Files Cleanup Complete** **Files Cleaned**: ${result.cleaned_files} **Directories Created**: ${result.directories_created.length > 0 ? result.directories_created.join(', ') : 'None'} **Patterns Processed**: ${result.patterns_cleaned.length > 0 ? result.patterns_cleaned.join(', ') : 'None'} ${result.errors.length > 0 ? `**Errors**: ${result.errors.join(', ')}` : 'โœ… No errors encountered'} ${result.cleaned_files > 0 ? 'Project cleanup successful!' : 'Project was already clean!'}` }] }; } catch (error) { return { content: [{ type: "text", text: `โŒ Error during cleanup: ${error.message}` }] }; } } export async function initializeProjectFile(templateType) { try { const result = await templateManager.initializeTemplate(templateType); if (result.skipped) { return { content: [{ type: "text", text: `โ„น๏ธ **Template Already Exists** ${result.message} The file was not overwritten to preserve your existing content.` }] }; } if (result.success) { return { content: [{ type: "text", text: `โœ… **Template Initialized Successfully** **Type**: ${templateType} **File**: ${result.file_path} ${result.message} You can now customize the generated file for your specific project needs.` }] }; } else { return { content: [{ type: "text", text: `โŒ **Template Initialization Failed** ${result.message} Please check that the template files are available and you have write permissions.` }] }; } } catch (error) { return { content: [{ type: "text", text: `โŒ Error initializing template: ${error.message}` }] }; } } export async function createTaskStructure(taskId, taskTitle) { try { const taskDir = join(PROJECT_ROOT, '.devflow', 'tasks', taskId); // Create task directory structure const directories = [ 'analysis', 'design', 'tests', 'implementation', 'refactor' ]; for (const dir of directories) { await fs.mkdir(join(taskDir, dir), { recursive: true }); } // Create initial task metadata file const taskMetadata = { id: taskId, title: taskTitle, created: new Date().toISOString(), status: 'pending', structure_version: await getVersion() }; await fs.writeFile(join(taskDir, 'task.yaml'), `# Task Metadata id: ${taskId} title: "${taskTitle}" created: ${taskMetadata.created} status: ${taskMetadata.status} structure_version: ${taskMetadata.structure_version} # Note: current_stage is managed in .devflow/state.json for consistency # This task.yaml focuses on task-specific metadata only # Folder Structure # analysis/ - Problem analysis and requirements # design/ - Architecture and design documents # tests/ - Test plans and test cases # implementation/ - Implementation notes and reviews # refactor/ - Refactoring plans and improvements `, 'utf-8'); // Create template files for analysis stage const analysisTemplate = `# file: .devflow/tasks/${taskId}/analysis/analysis.md # Analysis for ${taskTitle} ## Problem Statement [Describe the problem to solve] ## Requirements ### Functional Requirements - [ ] Requirement 1 - [ ] Requirement 2 ### Non-Functional Requirements - [ ] Performance requirements - [ ] Security requirements ## Approach [Outline your solution approach] ## Success Criteria - [ ] Criteria 1 - [ ] Criteria 2 ## Next Steps - [ ] Complete analysis - [ ] Move to design stage `; await fs.writeFile(join(taskDir, 'analysis', 'analysis.md'), analysisTemplate, 'utf-8'); return { content: [{ type: "text", text: `โœ… **Task Structure Created** **Task ID**: ${taskId} **Title**: ${taskTitle} **Location**: \`.devflow/tasks/${taskId}/\` **Created Directories**: - \`analysis/\` - Problem analysis and requirements - \`design/\` - Architecture and design documents - \`tests/\` - Test plans and test cases - \`implementation/\` - Implementation notes and reviews - \`refactor/\` - Refactoring plans and improvements **Template Files**: - \`task.yaml\` - Task metadata - \`analysis/analysis.md\` - Analysis template (ready to edit) **Next Steps**: 1. Edit \`.devflow/tasks/${taskId}/analysis/analysis.md\` 2. Use \`start_task\` with task_id: "${taskId}" 3. Use \`advance_stage\` when analysis is complete` }] }; } catch (error) { return { content: [{ type: "text", text: `โŒ Error creating task structure: ${error.message || error}` }] }; } } /** * Initialize a new Dev Flow project with complete structure (5-1) */ export async function initProject(options = {}) { const startTime = Date.now(); try { const { project_name = basename(PROJECT_ROOT), project_type = 'general', workflow_type = 'tdd_strict', include_templates = true } = options; console.log(`๐Ÿš€ Initializing Dev Flow project: ${project_name}`); // 1. Create .devflow directory structure const devflowDir = join(PROJECT_ROOT, '.devflow'); const directories = [ 'context', 'context/cache', 'tasks', 'workflows', 'templates', 'checkpoints', 'tmp' ]; console.log('๐Ÿ“ Creating directory structure...'); for (const dir of directories) { await fs.mkdir(join(devflowDir, dir), { recursive: true }); } // 2. Initialize project state console.log('โš™๏ธ Initializing project state...'); await stateManager.initializeProject(project_name); // 3. Create default workflows console.log('๐Ÿ”„ Setting up workflows...'); await simpleWorkflowManager.createDefaultWorkflows(); // Load the specified workflow const workflow = await simpleWorkflowManager.loadWorkflow(workflow_type); if (workflow) { const state = await stateManager.getCurrentState(); state.current_workflow = workflow_type; await stateManager.saveState(state); } // 4. Initialize templates based on project type if (include_templates) { console.log('๐Ÿ“„ Creating project templates...'); // Always create basic templates const basicTemplates = ['project_overview', 'tasklist', 'readme']; for (const template of basicTemplates) { try { await templateManager.initializeTemplate(template); } catch (error) { console.warn(`Warning: Could not create ${template} template:`, error); } } // Create requirements and design templates (5-2) console.log('๐Ÿ“‹ Creating requirements and design templates...'); const designTemplates = ['requirements', 'design_spec']; for (const template of designTemplates) { try { await templateManager.initializeTemplate(template); } catch (error) { console.warn(`Warning: Could not create ${template} template:`, error); } } } // 5. Create project-type specific structure and templates await createProjectTypeStructure(project_type, project_name); // 6. Create initial documentation await createInitialDocumentation(project_name, project_type, workflow_type); // 7. Create .gitignore for .devflow if needed await createGitIgnore(); const elapsedTime = Date.now() - startTime; const success = elapsedTime < 5000; // 5-second requirement return { content: [{ type: "text", text: `${success ? 'โœ…' : 'โš ๏ธ'} **Dev Flow Project Initialized** ${success ? '' : '(took longer than 5s)'} **Project**: ${project_name} **Type**: ${project_type} **Workflow**: ${workflow_type} **Time**: ${elapsedTime}ms **Created Structure**: \`\`\` .devflow/ โ”œโ”€โ”€ context/ # Context management โ”‚ โ””โ”€โ”€ cache/ # Context caching โ”œโ”€โ”€ tasks/ # Task-specific folders โ”œโ”€โ”€ workflows/ # Workflow definitions โ”œโ”€โ”€ templates/ # Project templates โ”œโ”€โ”€ checkpoints/ # Progress checkpoints โ”œโ”€โ”€ tmp/ # Temporary files โ””โ”€โ”€ state.yaml # Project state \`\`\` **Templates Created**: ${include_templates ? '- project_overview.md\n- tasklist.yaml\n- README.md\n- .devflow/requirements.md\n- .devflow/design_spec.md' : '- Basic structure only'} **Next Steps**: 1. Review and customize \`project_overview.md\` 2. Add your first task to \`tasklist.yaml\` 3. Use \`get_next_task\` to start development 4. Use \`load_workflow\` to switch workflows if needed ๐ŸŽ‰ **Ready to start developing with Dev Flow!**` }] }; } catch (error) { return { content: [{ type: "text", text: `โŒ **Project Initialization Failed** Error: ${error.message || error} Please ensure you have write permissions in the current directory and try again.` }] }; } } /** * Create project-type specific structure and files */ async function createProjectTypeStructure(projectType, projectName) { const devflowDir = join(PROJECT_ROOT, '.devflow'); // Create project-type specific directories and files switch (projectType) { case 'web': await fs.mkdir(join(devflowDir, 'assets'), { recursive: true }); await fs.writeFile(join(devflowDir, 'web-checklist.md'), `# Web Project Checklist for ${projectName} ## Frontend - [ ] HTML structure - [ ] CSS styling - [ ] JavaScript functionality - [ ] Responsive design - [ ] Cross-browser testing ## Performance - [ ] Image optimization - [ ] Code minification - [ ] Caching strategy - [ ] Performance testing ## Accessibility - [ ] ARIA labels - [ ] Keyboard navigation - [ ] Screen reader compatibility - [ ] Color contrast `); break; case 'api': await fs.mkdir(join(devflowDir, 'api-docs'), { recursive: true }); await fs.writeFile(join(devflowDir, 'api-checklist.md'), `# API Project Checklist for ${projectName} ## Development - [ ] API design and documentation - [ ] Endpoint implementation - [ ] Request/response validation - [ ] Error handling - [ ] Authentication/authorization ## Testing - [ ] Unit tests - [ ] Integration tests - [ ] API endpoint testing - [ ] Load testing - [ ] Security testing ## Documentation - [ ] OpenAPI/Swagger documentation - [ ] Usage examples - [ ] Rate limiting documentation `); break; case 'library': await fs.writeFile(join(devflowDir, 'library-checklist.md'), `# Library Project Checklist for ${projectName} ## Development - [ ] Public API design - [ ] Core functionality - [ ] Type definitions - [ ] Documentation - [ ] Examples ## Quality - [ ] Unit tests (>90% coverage) - [ ] Integration tests - [ ] Performance benchmarks - [ ] Browser/Node compatibility - [ ] Semantic versioning ## Distribution - [ ] Package.json configuration - [ ] Build process - [ ] Publishing workflow - [ ] Changelog maintenance `); break; case 'cli': await fs.writeFile(join(devflowDir, 'cli-checklist.md'), `# CLI Project Checklist for ${projectName} ## Development - [ ] Command structure design - [ ] Argument parsing - [ ] Help documentation - [ ] Error handling - [ ] Configuration management ## User Experience - [ ] Clear help messages - [ ] Progress indicators - [ ] Colored output - [ ] Interactive prompts - [ ] Shell completion ## Distribution - [ ] Cross-platform compatibility - [ ] Installation instructions - [ ] Man pages - [ ] Package distribution `); break; default: // General project - no specific structure break; } } /** * Create initial documentation files */ async function createInitialDocumentation(projectName, projectType, workflowType) { const devflowDir = join(PROJECT_ROOT, '.devflow'); // Create getting started guide const gettingStarted = `# Getting Started with ${projectName} ## Project Overview This is a ${projectType} project using Dev Flow for development workflow management. **Workflow**: ${workflowType} **Created**: ${new Date().toISOString().split('T')[0]} ## Quick Start 1. Review \`project_overview.md\` for project details 2. Check \`tasklist.yaml\` for available tasks 3. Use \`get_next_task\` to start your first task 4. Follow the ${workflowType} workflow stages ## Dev Flow Commands - \`get_next_task\` - Get the next task to work on - \`start_task\` - Start working on a specific task - \`check_progress\` - Check current progress - \`advance_stage\` - Move to the next workflow stage - \`save_checkpoint\` - Save current progress ## Project Structure \`\`\` .devflow/ โ”œโ”€โ”€ context/ # AI context management โ”œโ”€โ”€ tasks/ # Task-specific folders โ”œโ”€โ”€ workflows/ # Workflow definitions โ”œโ”€โ”€ templates/ # Project templates โ””โ”€โ”€ state.yaml # Current project state \`\`\` ## Tips - Use descriptive task names and IDs - Follow the workflow stages in order - Save checkpoints regularly - Keep task descriptions clear and actionable Happy coding! ๐Ÿš€ `; await fs.writeFile(join(devflowDir, 'getting-started.md'), gettingStarted); } /** * Create or update .gitignore for .devflow */ async function createGitIgnore() { const gitignorePath = join(PROJECT_ROOT, '.gitignore'); const devflowIgnoreRules = ` # Dev Flow temporary files .devflow/tmp/ .devflow/context/cache/ .devflow/checkpoints/*.bak # Dev Flow sensitive data (uncomment if needed) # .devflow/context/ # .devflow/state.yaml `; try { // Check if .gitignore exists const existingContent = await fs.readFile(gitignorePath, 'utf-8').catch(() => ''); // Only add if not already present if (!existingContent.includes('.devflow/tmp/')) { await fs.writeFile(gitignorePath, existingContent + devflowIgnoreRules); } } catch (error) { // Create new .gitignore if it doesn't exist await fs.writeFile(gitignorePath, devflowIgnoreRules.trim()); } } //# sourceMappingURL=project-tool-handlers.js.map