mirror of
https://github.com/eyaltoledano/claude-task-master.git
synced 2025-07-04 07:26:38 +00:00

This commit integrates AI usage telemetry for the `expand-task` command/tool and resolves issues related to incorrect return type handling and logging. Key Changes: 1. **Telemetry Integration for `expand-task` (Subtask 77.7):**\n - Applied the standard telemetry pattern to the `expandTask` core logic (`scripts/modules/task-manager/expand-task.js`) and the `expandTaskDirect` wrapper (`mcp-server/src/core/direct-functions/expand-task.js`).\n - AI service calls now pass `commandName` and `outputType`.\n - Core function returns `{ task, telemetryData }`.\n - Direct function correctly extracts `task` and passes `telemetryData` in the MCP response `data` field.\n - Telemetry summary is now displayed in the CLI output for the `expand` command. 2. **Fix AI Service Return Type Handling (`ai-services-unified.js`):**\n - Corrected the `_unifiedServiceRunner` function to properly handle the return objects from provider-specific functions (`generateText`, `generateObject`).\n - It now correctly extracts `providerResponse.text` or `providerResponse.object` into the `mainResult` field based on `serviceType`, resolving the "text.trim is not a function" error encountered during `expand-task`. 3. **Log Cleanup:**\n - Removed various redundant or excessive `console.log` statements across multiple files (as indicated by recent changes) to reduce noise and improve clarity, particularly for MCP interactions.
155 lines
4.4 KiB
JavaScript
155 lines
4.4 KiB
JavaScript
import fs from 'fs';
|
|
import path from 'path';
|
|
import chalk from 'chalk';
|
|
|
|
import { log, readJSON } from '../utils.js';
|
|
import { formatDependenciesWithStatus } from '../ui.js';
|
|
import { validateAndFixDependencies } from '../dependency-manager.js';
|
|
import { getDebugFlag } from '../config-manager.js';
|
|
|
|
/**
|
|
* Generate individual task files from tasks.json
|
|
* @param {string} tasksPath - Path to the tasks.json file
|
|
* @param {string} outputDir - Output directory for task files
|
|
* @param {Object} options - Additional options (mcpLog for MCP mode)
|
|
* @returns {Object|undefined} Result object in MCP mode, undefined in CLI mode
|
|
*/
|
|
function generateTaskFiles(tasksPath, outputDir, options = {}) {
|
|
try {
|
|
// Determine if we're in MCP mode by checking for mcpLog
|
|
const isMcpMode = !!options?.mcpLog;
|
|
|
|
const data = readJSON(tasksPath);
|
|
if (!data || !data.tasks) {
|
|
throw new Error(`No valid tasks found in ${tasksPath}`);
|
|
}
|
|
|
|
// Create the output directory if it doesn't exist
|
|
if (!fs.existsSync(outputDir)) {
|
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
}
|
|
|
|
log('info', `Preparing to regenerate ${data.tasks.length} task files`);
|
|
|
|
// Validate and fix dependencies before generating files
|
|
log('info', `Validating and fixing dependencies`);
|
|
validateAndFixDependencies(data, tasksPath);
|
|
|
|
// Generate task files
|
|
log('info', 'Generating individual task files...');
|
|
data.tasks.forEach((task) => {
|
|
const taskPath = path.join(
|
|
outputDir,
|
|
`task_${task.id.toString().padStart(3, '0')}.txt`
|
|
);
|
|
|
|
// Format the content
|
|
let content = `# Task ID: ${task.id}\n`;
|
|
content += `# Title: ${task.title}\n`;
|
|
content += `# Status: ${task.status || 'pending'}\n`;
|
|
|
|
// Format dependencies with their status
|
|
if (task.dependencies && task.dependencies.length > 0) {
|
|
content += `# Dependencies: ${formatDependenciesWithStatus(task.dependencies, data.tasks, false)}\n`;
|
|
} else {
|
|
content += '# Dependencies: None\n';
|
|
}
|
|
|
|
content += `# Priority: ${task.priority || 'medium'}\n`;
|
|
content += `# Description: ${task.description || ''}\n`;
|
|
|
|
// Add more detailed sections
|
|
content += '# Details:\n';
|
|
content += (task.details || '')
|
|
.split('\n')
|
|
.map((line) => line)
|
|
.join('\n');
|
|
content += '\n\n';
|
|
|
|
content += '# Test Strategy:\n';
|
|
content += (task.testStrategy || '')
|
|
.split('\n')
|
|
.map((line) => line)
|
|
.join('\n');
|
|
content += '\n';
|
|
|
|
// Add subtasks if they exist
|
|
if (task.subtasks && task.subtasks.length > 0) {
|
|
content += '\n# Subtasks:\n';
|
|
|
|
task.subtasks.forEach((subtask) => {
|
|
content += `## ${subtask.id}. ${subtask.title} [${subtask.status || 'pending'}]\n`;
|
|
|
|
if (subtask.dependencies && subtask.dependencies.length > 0) {
|
|
// Format subtask dependencies
|
|
let subtaskDeps = subtask.dependencies
|
|
.map((depId) => {
|
|
if (typeof depId === 'number') {
|
|
// Handle numeric dependencies to other subtasks
|
|
const foundSubtask = task.subtasks.find(
|
|
(st) => st.id === depId
|
|
);
|
|
if (foundSubtask) {
|
|
// Just return the plain ID format without any color formatting
|
|
return `${task.id}.${depId}`;
|
|
}
|
|
}
|
|
return depId.toString();
|
|
})
|
|
.join(', ');
|
|
|
|
content += `### Dependencies: ${subtaskDeps}\n`;
|
|
} else {
|
|
content += '### Dependencies: None\n';
|
|
}
|
|
|
|
content += `### Description: ${subtask.description || ''}\n`;
|
|
content += '### Details:\n';
|
|
content += (subtask.details || '')
|
|
.split('\n')
|
|
.map((line) => line)
|
|
.join('\n');
|
|
content += '\n\n';
|
|
});
|
|
}
|
|
|
|
// Write the file
|
|
fs.writeFileSync(taskPath, content);
|
|
// log('info', `Generated: task_${task.id.toString().padStart(3, '0')}.txt`); // Pollutes the CLI output
|
|
});
|
|
|
|
log(
|
|
'success',
|
|
`All ${data.tasks.length} tasks have been generated into '${outputDir}'.`
|
|
);
|
|
|
|
// Return success data in MCP mode
|
|
if (isMcpMode) {
|
|
return {
|
|
success: true,
|
|
count: data.tasks.length,
|
|
directory: outputDir
|
|
};
|
|
}
|
|
} catch (error) {
|
|
log('error', `Error generating task files: ${error.message}`);
|
|
|
|
// Only show error UI in CLI mode
|
|
if (!options?.mcpLog) {
|
|
console.error(chalk.red(`Error generating task files: ${error.message}`));
|
|
|
|
if (getDebugFlag()) {
|
|
// Use getter
|
|
console.error(error);
|
|
}
|
|
|
|
process.exit(1);
|
|
} else {
|
|
// In MCP mode, throw the error for the caller to handle
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
export default generateTaskFiles;
|