mirror of
https://github.com/eyaltoledano/claude-task-master.git
synced 2025-11-23 13:36:44 +00:00
- Enhance MCP server robustness and usability: - Implement smart project root detection with hierarchical fallbacks - Make projectRoot parameter optional across all MCP tools - Add comprehensive PROJECT_MARKERS for reliable project detection - Improve error messages and logging for better debugging - Split monolithic core into focused direct-function files - Implement full suite of MCP commands: - Add task management: update-task, update-subtask, generate - Add task organization: expand-task, expand-all, clear-subtasks - Add dependency handling: add/remove/validate/fix dependencies - Add analysis tools: analyze-complexity, complexity-report - Rename commands for better API consistency (list-tasks → get-tasks) - Enhance documentation and developer experience: - Create and bundle new taskmaster.mdc as comprehensive reference - Document all tools with natural language patterns and examples - Clarify project root auto-detection in documentation - Standardize naming conventions across MCP components - Add cross-references between related tools and commands - Improve UI and progress tracking: - Add color-coded progress bars with status breakdown - Implement cancelled/deferred task status handling - Enhance status visualization and counting - Optimize display for various terminal sizes This major update significantly improves the robustness and usability of the MCP server while providing comprehensive documentation for both users and developers. The changes make Task Master more intuitive to use programmatically while maintaining full CLI functionality.
197 lines
5.7 KiB
JavaScript
Executable File
197 lines
5.7 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
/**
|
|
* This script prepares the package for publication to NPM.
|
|
* It ensures all necessary files are included and properly configured.
|
|
*
|
|
* Additional options:
|
|
* --patch: Increment patch version (default)
|
|
* --minor: Increment minor version
|
|
* --major: Increment major version
|
|
* --version=x.y.z: Set specific version
|
|
*/
|
|
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import { execSync } from 'child_process';
|
|
import { fileURLToPath } from 'url';
|
|
import { dirname } from 'path';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
// Define colors for console output
|
|
const COLORS = {
|
|
reset: '\x1b[0m',
|
|
bright: '\x1b[1m',
|
|
dim: '\x1b[2m',
|
|
red: '\x1b[31m',
|
|
green: '\x1b[32m',
|
|
yellow: '\x1b[33m',
|
|
blue: '\x1b[34m',
|
|
magenta: '\x1b[35m',
|
|
cyan: '\x1b[36m'
|
|
};
|
|
|
|
// Parse command line arguments
|
|
const args = process.argv.slice(2);
|
|
const versionBump = args.includes('--major') ? 'major' :
|
|
args.includes('--minor') ? 'minor' :
|
|
'patch';
|
|
|
|
// Check for explicit version
|
|
const versionArg = args.find(arg => arg.startsWith('--version='));
|
|
const explicitVersion = versionArg ? versionArg.split('=')[1] : null;
|
|
|
|
// Log function with color support
|
|
function log(level, ...args) {
|
|
const prefix = {
|
|
info: `${COLORS.blue}[INFO]${COLORS.reset}`,
|
|
warn: `${COLORS.yellow}[WARN]${COLORS.reset}`,
|
|
error: `${COLORS.red}[ERROR]${COLORS.reset}`,
|
|
success: `${COLORS.green}[SUCCESS]${COLORS.reset}`
|
|
}[level.toLowerCase()];
|
|
|
|
console.log(prefix, ...args);
|
|
}
|
|
|
|
// Function to check if a file exists
|
|
function fileExists(filePath) {
|
|
return fs.existsSync(filePath);
|
|
}
|
|
|
|
// Function to ensure a file is executable
|
|
function ensureExecutable(filePath) {
|
|
try {
|
|
fs.chmodSync(filePath, '755');
|
|
log('info', `Made ${filePath} executable`);
|
|
} catch (error) {
|
|
log('error', `Failed to make ${filePath} executable:`, error.message);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Function to sync template files
|
|
function syncTemplateFiles() {
|
|
// We no longer need to sync files since we're using them directly
|
|
log('info', 'Template syncing has been deprecated - using source files directly');
|
|
return true;
|
|
}
|
|
|
|
// Function to increment version
|
|
function incrementVersion(currentVersion, type = 'patch') {
|
|
const [major, minor, patch] = currentVersion.split('.').map(Number);
|
|
|
|
switch (type) {
|
|
case 'major':
|
|
return `${major + 1}.0.0`;
|
|
case 'minor':
|
|
return `${major}.${minor + 1}.0`;
|
|
case 'patch':
|
|
default:
|
|
return `${major}.${minor}.${patch + 1}`;
|
|
}
|
|
}
|
|
|
|
// Main function to prepare the package
|
|
function preparePackage() {
|
|
const rootDir = path.join(__dirname, '..');
|
|
log('info', `Preparing package in ${rootDir}`);
|
|
|
|
// Update version in package.json
|
|
const packageJsonPath = path.join(rootDir, 'package.json');
|
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
const currentVersion = packageJson.version;
|
|
|
|
let newVersion;
|
|
if (explicitVersion) {
|
|
newVersion = explicitVersion;
|
|
log('info', `Setting version to specified ${newVersion} (was ${currentVersion})`);
|
|
} else {
|
|
newVersion = incrementVersion(currentVersion, versionBump);
|
|
log('info', `Incrementing ${versionBump} version to ${newVersion} (was ${currentVersion})`);
|
|
}
|
|
|
|
packageJson.version = newVersion;
|
|
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
log('success', `Updated package.json version to ${newVersion}`);
|
|
|
|
// Check for required files
|
|
const requiredFiles = [
|
|
'package.json',
|
|
'README-task-master.md',
|
|
'index.js',
|
|
'scripts/init.js',
|
|
'scripts/dev.js',
|
|
'assets/env.example',
|
|
'assets/gitignore',
|
|
'assets/example_prd.txt',
|
|
'assets/scripts_README.md',
|
|
'.cursor/rules/dev_workflow.mdc',
|
|
'.cursor/rules/taskmaster.mdc',
|
|
'.cursor/rules/cursor_rules.mdc',
|
|
'.cursor/rules/self_improve.mdc'
|
|
];
|
|
|
|
let allFilesExist = true;
|
|
for (const file of requiredFiles) {
|
|
const filePath = path.join(rootDir, file);
|
|
if (!fileExists(filePath)) {
|
|
log('error', `Required file ${file} does not exist`);
|
|
allFilesExist = false;
|
|
}
|
|
}
|
|
|
|
if (!allFilesExist) {
|
|
log('error', 'Some required files are missing. Package preparation failed.');
|
|
process.exit(1);
|
|
}
|
|
|
|
// Ensure scripts are executable
|
|
const executableScripts = [
|
|
'scripts/init.js',
|
|
'scripts/dev.js'
|
|
];
|
|
|
|
let allScriptsExecutable = true;
|
|
for (const script of executableScripts) {
|
|
const scriptPath = path.join(rootDir, script);
|
|
if (!ensureExecutable(scriptPath)) {
|
|
allScriptsExecutable = false;
|
|
}
|
|
}
|
|
|
|
if (!allScriptsExecutable) {
|
|
log('warn', 'Some scripts could not be made executable. This may cause issues.');
|
|
}
|
|
|
|
// Run npm pack to test package creation
|
|
try {
|
|
log('info', 'Running npm pack to test package creation...');
|
|
const output = execSync('npm pack --dry-run', { cwd: rootDir }).toString();
|
|
log('info', output);
|
|
} catch (error) {
|
|
log('error', 'Failed to run npm pack:', error.message);
|
|
process.exit(1);
|
|
}
|
|
|
|
// Make scripts executable
|
|
log('info', 'Making scripts executable...');
|
|
try {
|
|
execSync('chmod +x scripts/init.js', { stdio: 'ignore' });
|
|
log('info', 'Made scripts/init.js executable');
|
|
execSync('chmod +x scripts/dev.js', { stdio: 'ignore' });
|
|
log('info', 'Made scripts/dev.js executable');
|
|
} catch (error) {
|
|
log('error', 'Failed to make scripts executable:', error.message);
|
|
}
|
|
|
|
log('success', `Package preparation completed successfully! 🎉`);
|
|
log('success', `Version updated to ${newVersion}`);
|
|
log('info', 'You can now publish the package with:');
|
|
log('info', ' npm publish');
|
|
}
|
|
|
|
// Run the preparation
|
|
preparePackage();
|