feat: adds remove-task command + MCP implementation.

This commit is contained in:
Eyal Toledano
2025-04-03 00:35:11 -04:00
parent 6442bf5ee1
commit cdd87ccc5e
15 changed files with 1204 additions and 26 deletions

View File

@@ -9,6 +9,7 @@ import chalk from 'chalk';
import boxen from 'boxen';
import fs from 'fs';
import https from 'https';
import inquirer from 'inquirer';
import { CONFIG, log, readJSON } from './utils.js';
import {
@@ -25,7 +26,10 @@ import {
removeSubtask,
analyzeTaskComplexity,
updateTaskById,
updateSubtaskById
updateSubtaskById,
removeTask,
findTaskById,
taskExists
} from './task-manager.js';
import {
@@ -42,7 +46,9 @@ import {
displayTaskById,
displayComplexityReport,
getStatusWithColor,
confirmTaskOverwrite
confirmTaskOverwrite,
startLoadingIndicator,
stopLoadingIndicator
} from './ui.js';
/**
@@ -863,7 +869,120 @@ function registerCommands(programInstance) {
console.log(chalk.white(' task-master init -y'));
process.exit(0);
});
// remove-task command
programInstance
.command('remove-task')
.description('Remove a task or subtask permanently')
.option('-i, --id <id>', 'ID of the task or subtask to remove (e.g., "5" or "5.2")')
.option('-f, --file <file>', 'Path to the tasks file', 'tasks/tasks.json')
.option('-y, --yes', 'Skip confirmation prompt', false)
.action(async (options) => {
const tasksPath = options.file;
const taskId = options.id;
if (!taskId) {
console.error(chalk.red('Error: Task ID is required'));
console.error(chalk.yellow('Usage: task-master remove-task --id=<taskId>'));
process.exit(1);
}
try {
// Check if the task exists
const data = readJSON(tasksPath);
if (!data || !data.tasks) {
console.error(chalk.red(`Error: No valid tasks found in ${tasksPath}`));
process.exit(1);
}
if (!taskExists(data.tasks, taskId)) {
console.error(chalk.red(`Error: Task with ID ${taskId} not found`));
process.exit(1);
}
// Load task for display
const task = findTaskById(data.tasks, taskId);
// Skip confirmation if --yes flag is provided
if (!options.yes) {
// Display task information
console.log();
console.log(chalk.red.bold('⚠️ WARNING: This will permanently delete the following task:'));
console.log();
if (typeof taskId === 'string' && taskId.includes('.')) {
// It's a subtask
const [parentId, subtaskId] = taskId.split('.');
console.log(chalk.white.bold(`Subtask ${taskId}: ${task.title}`));
console.log(chalk.gray(`Parent Task: ${task.parentTask.id} - ${task.parentTask.title}`));
} else {
// It's a main task
console.log(chalk.white.bold(`Task ${taskId}: ${task.title}`));
// Show if it has subtasks
if (task.subtasks && task.subtasks.length > 0) {
console.log(chalk.yellow(`⚠️ This task has ${task.subtasks.length} subtasks that will also be deleted!`));
}
// Show if other tasks depend on it
const dependentTasks = data.tasks.filter(t =>
t.dependencies && t.dependencies.includes(parseInt(taskId, 10)));
if (dependentTasks.length > 0) {
console.log(chalk.yellow(`⚠️ Warning: ${dependentTasks.length} other tasks depend on this task!`));
console.log(chalk.yellow('These dependencies will be removed:'));
dependentTasks.forEach(t => {
console.log(chalk.yellow(` - Task ${t.id}: ${t.title}`));
});
}
}
console.log();
// Prompt for confirmation
const { confirm } = await inquirer.prompt([
{
type: 'confirm',
name: 'confirm',
message: chalk.red.bold('Are you sure you want to permanently delete this task?'),
default: false
}
]);
if (!confirm) {
console.log(chalk.blue('Task deletion cancelled.'));
process.exit(0);
}
}
const indicator = startLoadingIndicator('Removing task...');
// Remove the task
const result = await removeTask(tasksPath, taskId);
stopLoadingIndicator(indicator);
// Display success message with appropriate color based on task or subtask
if (typeof taskId === 'string' && taskId.includes('.')) {
// It was a subtask
console.log(boxen(
chalk.green(`Subtask ${taskId} has been successfully removed`),
{ padding: 1, borderColor: 'green', borderStyle: 'round' }
));
} else {
// It was a main task
console.log(boxen(
chalk.green(`Task ${taskId} has been successfully removed`),
{ padding: 1, borderColor: 'green', borderStyle: 'round' }
));
}
} catch (error) {
console.error(chalk.red(`Error: ${error.message || 'An unknown error occurred'}`));
process.exit(1);
}
});
// Add more commands as needed...
return programInstance;