chore: changeset + update rules.

This commit is contained in:
Eyal Toledano
2025-04-03 04:09:27 -04:00
parent 68f0bfc811
commit a908109cf7
54 changed files with 1462 additions and 316 deletions

View File

@@ -20,7 +20,9 @@ import {
findTaskById,
readComplexityReport,
findTaskInComplexityReport,
truncate
truncate,
enableSilentMode,
disableSilentMode
} from './utils.js';
import {
@@ -102,7 +104,14 @@ async function parsePRD(prdPath, tasksPath, numTasks, { reportProgress, mcpLog,
log('info', `Tasks saved to: ${tasksPath}`);
// Generate individual task files
await generateTaskFiles(tasksPath, tasksDir, { reportProgress, mcpLog, session } = {});
if (reportProgress && mcpLog) {
// Enable silent mode when being called from MCP server
enableSilentMode();
await generateTaskFiles(tasksPath, tasksDir);
disableSilentMode();
} else {
await generateTaskFiles(tasksPath, tasksDir);
}
console.log(boxen(
chalk.green(`Successfully generated ${tasksData.tasks.length} tasks from PRD`),
@@ -762,6 +771,7 @@ Return only the updated task as a valid JSON object.`
function generateTaskFiles(tasksPath, outputDir) {
try {
log('info', `Reading tasks from ${tasksPath}...`);
const data = readJSON(tasksPath);
if (!data || !data.tasks) {
throw new Error(`No valid tasks found in ${tasksPath}`);
@@ -2059,8 +2069,16 @@ function clearSubtasks(tasksPath, taskIds) {
* @param {Object} session - Session object from MCP server (optional)
* @returns {number} The new task ID
*/
async function addTask(tasksPath, prompt, dependencies = [], priority = 'medium', { reportProgress, mcpLog, session } = {}) {
displayBanner();
async function addTask(tasksPath, prompt, dependencies = [], priority = 'medium', { reportProgress, mcpLog, session } = {}, outputFormat = 'text') {
// Only display banner and UI elements for text output (CLI)
if (outputFormat === 'text') {
displayBanner();
console.log(boxen(
chalk.white.bold(`Creating New Task`),
{ padding: 1, borderColor: 'blue', borderStyle: 'round', margin: { top: 1, bottom: 1 } }
));
}
// Read the existing tasks
const data = readJSON(tasksPath);
@@ -2073,10 +2091,13 @@ async function addTask(tasksPath, prompt, dependencies = [], priority = 'medium'
const highestId = Math.max(...data.tasks.map(t => t.id));
const newTaskId = highestId + 1;
console.log(boxen(
chalk.white.bold(`Creating New Task #${newTaskId}`),
{ padding: 1, borderColor: 'blue', borderStyle: 'round', margin: { top: 1, bottom: 1 } }
));
// Only show UI box for CLI mode
if (outputFormat === 'text') {
console.log(boxen(
chalk.white.bold(`Creating New Task #${newTaskId}`),
{ padding: 1, borderColor: 'blue', borderStyle: 'round', margin: { top: 1, bottom: 1 } }
));
}
// Validate dependencies before proceeding
const invalidDeps = dependencies.filter(depId => {
@@ -2126,8 +2147,11 @@ async function addTask(tasksPath, prompt, dependencies = [], priority = 'medium'
IMPORTANT: Return ONLY the JSON object, nothing else.`;
// Start the loading indicator
const loadingIndicator = startLoadingIndicator('Generating new task with Claude AI...');
// Start the loading indicator - only for text mode
let loadingIndicator = null;
if (outputFormat === 'text') {
loadingIndicator = startLoadingIndicator('Generating new task with Claude AI...');
}
let fullResponse = '';
let streamingInterval = null;
@@ -2143,13 +2167,15 @@ async function addTask(tasksPath, prompt, dependencies = [], priority = 'medium'
stream: true
});
// Update loading indicator to show streaming progress
// Update loading indicator to show streaming progress - only for text mode
let dotCount = 0;
streamingInterval = setInterval(() => {
readline.cursorTo(process.stdout, 0);
process.stdout.write(`Receiving streaming response from Claude${'.'.repeat(dotCount)}`);
dotCount = (dotCount + 1) % 4;
}, 500);
if (outputFormat === 'text') {
streamingInterval = setInterval(() => {
readline.cursorTo(process.stdout, 0);
process.stdout.write(`Receiving streaming response from Claude${'.'.repeat(dotCount)}`);
dotCount = (dotCount + 1) % 4;
}, 500);
}
// Process the stream
for await (const chunk of stream) {
@@ -2166,7 +2192,7 @@ async function addTask(tasksPath, prompt, dependencies = [], priority = 'medium'
}
if (streamingInterval) clearInterval(streamingInterval);
stopLoadingIndicator(loadingIndicator);
if (loadingIndicator) stopLoadingIndicator(loadingIndicator);
log('info', "Completed streaming response from Claude API!");
log('debug', `Streaming response length: ${fullResponse.length} characters`);
@@ -2213,28 +2239,31 @@ async function addTask(tasksPath, prompt, dependencies = [], priority = 'medium'
// Write the updated tasks back to the file
writeJSON(tasksPath, data);
// Show success message
const successBox = boxen(
chalk.green(`Successfully added new task #${newTaskId}:\n`) +
chalk.white.bold(newTask.title) + "\n\n" +
chalk.white(newTask.description),
{ padding: 1, borderColor: 'green', borderStyle: 'round', margin: { top: 1 } }
);
console.log(successBox);
// Next steps suggestion
console.log(boxen(
chalk.white.bold('Next Steps:') + '\n\n' +
`${chalk.cyan('1.')} Run ${chalk.yellow('task-master generate')} to update task files\n` +
`${chalk.cyan('2.')} Run ${chalk.yellow('task-master expand --id=' + newTaskId)} to break it down into subtasks\n` +
`${chalk.cyan('3.')} Run ${chalk.yellow('task-master list --with-subtasks')} to see all tasks`,
{ padding: 1, borderColor: 'cyan', borderStyle: 'round', margin: { top: 1 } }
));
// Only show success messages for text mode (CLI)
if (outputFormat === 'text') {
// Show success message
const successBox = boxen(
chalk.green(`Successfully added new task #${newTaskId}:\n`) +
chalk.white.bold(newTask.title) + "\n\n" +
chalk.white(newTask.description),
{ padding: 1, borderColor: 'green', borderStyle: 'round', margin: { top: 1 } }
);
console.log(successBox);
// Next steps suggestion
console.log(boxen(
chalk.white.bold('Next Steps:') + '\n\n' +
`${chalk.cyan('1.')} Run ${chalk.yellow('task-master generate')} to update task files\n` +
`${chalk.cyan('2.')} Run ${chalk.yellow('task-master expand --id=' + newTaskId)} to break it down into subtasks\n` +
`${chalk.cyan('3.')} Run ${chalk.yellow('task-master list --with-subtasks')} to see all tasks`,
{ padding: 1, borderColor: 'cyan', borderStyle: 'round', margin: { top: 1 } }
));
}
return newTaskId;
} catch (error) {
if (streamingInterval) clearInterval(streamingInterval);
stopLoadingIndicator(loadingIndicator);
if (loadingIndicator) stopLoadingIndicator(loadingIndicator);
log('error', "Error generating task:", error.message);
process.exit(1);
}

View File

@@ -20,6 +20,9 @@ const CONFIG = {
projectVersion: "1.5.0" // Hardcoded version - ALWAYS use this value, ignore environment variable
};
// Global silent mode flag
let silentMode = false;
// Set up logging based on log level
const LOG_LEVELS = {
debug: 0,
@@ -28,23 +31,51 @@ const LOG_LEVELS = {
error: 3
};
/**
* Enable silent logging mode
*/
function enableSilentMode() {
silentMode = true;
}
/**
* Disable silent logging mode
*/
function disableSilentMode() {
silentMode = false;
}
/**
* Check if silent mode is enabled
* @returns {boolean} True if silent mode is enabled
*/
function isSilentMode() {
return silentMode;
}
/**
* Logs a message at the specified level
* @param {string} level - The log level (debug, info, warn, error)
* @param {...any} args - Arguments to log
*/
function log(level, ...args) {
const icons = {
debug: chalk.gray('🔍'),
info: chalk.blue(''),
warn: chalk.yellow('⚠️'),
error: chalk.red('❌'),
success: chalk.green('✅')
// Skip logging if silent mode is enabled
if (silentMode) {
return;
}
// Use text prefixes instead of emojis
const prefixes = {
debug: chalk.gray("[DEBUG]"),
info: chalk.blue("[INFO]"),
warn: chalk.yellow("[WARN]"),
error: chalk.red("[ERROR]"),
success: chalk.green("[SUCCESS]")
};
if (LOG_LEVELS[level] >= LOG_LEVELS[CONFIG.logLevel]) {
const icon = icons[level] || '';
console.log(`${icon} ${args.join(' ')}`);
const prefix = prefixes[level] || "";
console.log(`${prefix} ${args.join(' ')}`);
}
}
@@ -337,5 +368,8 @@ export {
truncate,
findCycles,
toKebabCase,
detectCamelCaseFlags
detectCamelCaseFlags,
enableSilentMode,
disableSilentMode,
isSilentMode
};