@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
JavaScript
/**
* 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