Merge branch 'next' of https://github.com/eyaltoledano/claude-task-master into joedanz/flexible-brand-rules
# Conflicts: # scripts/modules/commands.js # scripts/modules/ui.js
This commit is contained in:
@@ -94,6 +94,7 @@ export async function addTaskDirect(args, log, context = {}) {
|
||||
|
||||
let manualTaskData = null;
|
||||
let newTaskId;
|
||||
let telemetryData;
|
||||
|
||||
if (isManualCreation) {
|
||||
// Create manual task data object
|
||||
@@ -109,7 +110,7 @@ export async function addTaskDirect(args, log, context = {}) {
|
||||
);
|
||||
|
||||
// Call the addTask function with manual task data
|
||||
newTaskId = await addTask(
|
||||
const result = await addTask(
|
||||
tasksPath,
|
||||
null, // prompt is null for manual creation
|
||||
taskDependencies,
|
||||
@@ -117,13 +118,17 @@ export async function addTaskDirect(args, log, context = {}) {
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
projectRoot
|
||||
projectRoot,
|
||||
commandName: 'add-task',
|
||||
outputType: 'mcp'
|
||||
},
|
||||
'json', // outputFormat
|
||||
manualTaskData, // Pass the manual task data
|
||||
false, // research flag is false for manual creation
|
||||
projectRoot // Pass projectRoot
|
||||
);
|
||||
newTaskId = result.newTaskId;
|
||||
telemetryData = result.telemetryData;
|
||||
} else {
|
||||
// AI-driven task creation
|
||||
log.info(
|
||||
@@ -131,7 +136,7 @@ export async function addTaskDirect(args, log, context = {}) {
|
||||
);
|
||||
|
||||
// Call the addTask function, passing the research flag
|
||||
newTaskId = await addTask(
|
||||
const result = await addTask(
|
||||
tasksPath,
|
||||
prompt, // Use the prompt for AI creation
|
||||
taskDependencies,
|
||||
@@ -139,12 +144,16 @@ export async function addTaskDirect(args, log, context = {}) {
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
projectRoot
|
||||
projectRoot,
|
||||
commandName: 'add-task',
|
||||
outputType: 'mcp'
|
||||
},
|
||||
'json', // outputFormat
|
||||
null, // manualTaskData is null for AI creation
|
||||
research // Pass the research flag
|
||||
);
|
||||
newTaskId = result.newTaskId;
|
||||
telemetryData = result.telemetryData;
|
||||
}
|
||||
|
||||
// Restore normal logging
|
||||
@@ -154,7 +163,8 @@ export async function addTaskDirect(args, log, context = {}) {
|
||||
success: true,
|
||||
data: {
|
||||
taskId: newTaskId,
|
||||
message: `Successfully added new task #${newTaskId}`
|
||||
message: `Successfully added new task #${newTaskId}`,
|
||||
telemetryData: telemetryData
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
|
||||
@@ -79,17 +79,19 @@ export async function analyzeTaskComplexityDirect(args, log, context = {}) {
|
||||
}
|
||||
|
||||
let report;
|
||||
let coreResult;
|
||||
|
||||
try {
|
||||
// --- Call Core Function (Pass context separately) ---
|
||||
// Pass coreOptions as the first argument
|
||||
// Pass context object { session, mcpLog } as the second argument
|
||||
report = await analyzeTaskComplexity(
|
||||
coreOptions, // Pass options object
|
||||
{ session, mcpLog: logWrapper } // Pass context object
|
||||
// Removed the explicit 'json' format argument, assuming context handling is sufficient
|
||||
// If issues persist, we might need to add an explicit format param to analyzeTaskComplexity
|
||||
);
|
||||
coreResult = await analyzeTaskComplexity(coreOptions, {
|
||||
session,
|
||||
mcpLog: logWrapper,
|
||||
commandName: 'analyze-complexity',
|
||||
outputType: 'mcp'
|
||||
});
|
||||
report = coreResult.report;
|
||||
} catch (error) {
|
||||
log.error(
|
||||
`Error in analyzeTaskComplexity core function: ${error.message}`
|
||||
@@ -125,8 +127,11 @@ export async function analyzeTaskComplexityDirect(args, log, context = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
// Added a check to ensure report is defined before accessing its properties
|
||||
if (!report || typeof report !== 'object') {
|
||||
if (
|
||||
!coreResult ||
|
||||
!coreResult.report ||
|
||||
typeof coreResult.report !== 'object'
|
||||
) {
|
||||
log.error(
|
||||
'Core analysis function returned an invalid or undefined response.'
|
||||
);
|
||||
@@ -141,8 +146,8 @@ export async function analyzeTaskComplexityDirect(args, log, context = {}) {
|
||||
|
||||
try {
|
||||
// Ensure complexityAnalysis exists and is an array
|
||||
const analysisArray = Array.isArray(report.complexityAnalysis)
|
||||
? report.complexityAnalysis
|
||||
const analysisArray = Array.isArray(coreResult.report.complexityAnalysis)
|
||||
? coreResult.report.complexityAnalysis
|
||||
: [];
|
||||
|
||||
// Count tasks by complexity (remains the same)
|
||||
@@ -159,15 +164,16 @@ export async function analyzeTaskComplexityDirect(args, log, context = {}) {
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
message: `Task complexity analysis complete. Report saved to ${outputPath}`, // Use outputPath from args
|
||||
reportPath: outputPath, // Use outputPath from args
|
||||
message: `Task complexity analysis complete. Report saved to ${outputPath}`,
|
||||
reportPath: outputPath,
|
||||
reportSummary: {
|
||||
taskCount: analysisArray.length,
|
||||
highComplexityTasks,
|
||||
mediumComplexityTasks,
|
||||
lowComplexityTasks
|
||||
},
|
||||
fullReport: report // Now includes the full report
|
||||
fullReport: coreResult.report,
|
||||
telemetryData: coreResult.telemetryData
|
||||
}
|
||||
};
|
||||
} catch (parseError) {
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { getCachedOrExecute } from '../../tools/utils.js';
|
||||
|
||||
/**
|
||||
* Direct function wrapper for displaying the complexity report with error handling and caching.
|
||||
@@ -86,30 +85,20 @@ export async function complexityReportDirect(args, log) {
|
||||
|
||||
// Use the caching utility
|
||||
try {
|
||||
const result = await getCachedOrExecute({
|
||||
cacheKey,
|
||||
actionFn: coreActionFn,
|
||||
log
|
||||
});
|
||||
log.info(
|
||||
`complexityReportDirect completed. From cache: ${result.fromCache}`
|
||||
);
|
||||
return result; // Returns { success, data/error, fromCache }
|
||||
const result = await coreActionFn();
|
||||
log.info('complexityReportDirect completed');
|
||||
return result;
|
||||
} catch (error) {
|
||||
// Catch unexpected errors from getCachedOrExecute itself
|
||||
// Ensure silent mode is disabled
|
||||
disableSilentMode();
|
||||
|
||||
log.error(
|
||||
`Unexpected error during getCachedOrExecute for complexityReport: ${error.message}`
|
||||
);
|
||||
log.error(`Unexpected error during complexityReport: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'UNEXPECTED_ERROR',
|
||||
message: error.message
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -63,12 +63,18 @@ export async function expandAllTasksDirect(args, log, context = {}) {
|
||||
{ session, mcpLog, projectRoot }
|
||||
);
|
||||
|
||||
// Core function now returns a summary object
|
||||
// Core function now returns a summary object including the *aggregated* telemetryData
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
message: `Expand all operation completed. Expanded: ${result.expandedCount}, Failed: ${result.failedCount}, Skipped: ${result.skippedCount}`,
|
||||
details: result // Include the full result details
|
||||
details: {
|
||||
expandedCount: result.expandedCount,
|
||||
failedCount: result.failedCount,
|
||||
skippedCount: result.skippedCount,
|
||||
tasksToExpand: result.tasksToExpand
|
||||
},
|
||||
telemetryData: result.telemetryData // Pass the aggregated object
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
|
||||
@@ -193,13 +193,19 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
if (!wasSilent) enableSilentMode();
|
||||
|
||||
// Call the core expandTask function with the wrapped logger and projectRoot
|
||||
const updatedTaskResult = await expandTask(
|
||||
const coreResult = await expandTask(
|
||||
tasksPath,
|
||||
taskId,
|
||||
numSubtasks,
|
||||
useResearch,
|
||||
additionalContext,
|
||||
{ mcpLog, session, projectRoot },
|
||||
{
|
||||
mcpLog,
|
||||
session,
|
||||
projectRoot,
|
||||
commandName: 'expand-task',
|
||||
outputType: 'mcp'
|
||||
},
|
||||
forceFlag
|
||||
);
|
||||
|
||||
@@ -215,16 +221,17 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
? updatedTask.subtasks.length - subtasksCountBefore
|
||||
: 0;
|
||||
|
||||
// Return the result
|
||||
// Return the result, including telemetryData
|
||||
log.info(
|
||||
`Successfully expanded task ${taskId} with ${subtasksAdded} new subtasks`
|
||||
);
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
task: updatedTask,
|
||||
task: coreResult.task,
|
||||
subtasksAdded,
|
||||
hasExistingSubtasks
|
||||
hasExistingSubtasks,
|
||||
telemetryData: coreResult.telemetryData
|
||||
},
|
||||
fromCache: false
|
||||
};
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
import { listTasks } from '../../../../scripts/modules/task-manager.js';
|
||||
import { getCachedOrExecute } from '../../tools/utils.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
@@ -19,7 +18,7 @@ import {
|
||||
*/
|
||||
export async function listTasksDirect(args, log) {
|
||||
// Destructure the explicit tasksJsonPath from args
|
||||
const { tasksJsonPath, status, withSubtasks } = args;
|
||||
const { tasksJsonPath, reportPath, status, withSubtasks } = args;
|
||||
|
||||
if (!tasksJsonPath) {
|
||||
log.error('listTasksDirect called without tasksJsonPath');
|
||||
@@ -36,7 +35,6 @@ export async function listTasksDirect(args, log) {
|
||||
// Use the explicit tasksJsonPath for cache key
|
||||
const statusFilter = status || 'all';
|
||||
const withSubtasksFilter = withSubtasks || false;
|
||||
const cacheKey = `listTasks:${tasksJsonPath}:${statusFilter}:${withSubtasksFilter}`;
|
||||
|
||||
// Define the action function to be executed on cache miss
|
||||
const coreListTasksAction = async () => {
|
||||
@@ -51,6 +49,7 @@ export async function listTasksDirect(args, log) {
|
||||
const resultData = listTasks(
|
||||
tasksJsonPath,
|
||||
statusFilter,
|
||||
reportPath,
|
||||
withSubtasksFilter,
|
||||
'json'
|
||||
);
|
||||
@@ -65,6 +64,7 @@ export async function listTasksDirect(args, log) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
log.info(
|
||||
`Core listTasks function retrieved ${resultData.tasks.length} tasks`
|
||||
);
|
||||
@@ -88,25 +88,19 @@ export async function listTasksDirect(args, log) {
|
||||
}
|
||||
};
|
||||
|
||||
// Use the caching utility
|
||||
try {
|
||||
const result = await getCachedOrExecute({
|
||||
cacheKey,
|
||||
actionFn: coreListTasksAction,
|
||||
log
|
||||
});
|
||||
log.info(`listTasksDirect completed. From cache: ${result.fromCache}`);
|
||||
return result; // Returns { success, data/error, fromCache }
|
||||
const result = await coreListTasksAction();
|
||||
log.info('listTasksDirect completed');
|
||||
return result;
|
||||
} catch (error) {
|
||||
// Catch unexpected errors from getCachedOrExecute itself (though unlikely)
|
||||
log.error(
|
||||
`Unexpected error during getCachedOrExecute for listTasks: ${error.message}`
|
||||
);
|
||||
log.error(`Unexpected error during listTasks: ${error.message}`);
|
||||
console.error(error.stack);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'CACHE_UTIL_ERROR', message: error.message },
|
||||
fromCache: false
|
||||
error: {
|
||||
code: 'UNEXPECTED_ERROR',
|
||||
message: error.message
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
*/
|
||||
|
||||
import { findNextTask } from '../../../../scripts/modules/task-manager.js';
|
||||
import { readJSON } from '../../../../scripts/modules/utils.js';
|
||||
import { getCachedOrExecute } from '../../tools/utils.js';
|
||||
import {
|
||||
readJSON,
|
||||
readComplexityReport
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
@@ -21,7 +23,7 @@ import {
|
||||
*/
|
||||
export async function nextTaskDirect(args, log) {
|
||||
// Destructure expected args
|
||||
const { tasksJsonPath } = args;
|
||||
const { tasksJsonPath, reportPath } = args;
|
||||
|
||||
if (!tasksJsonPath) {
|
||||
log.error('nextTaskDirect called without tasksJsonPath');
|
||||
@@ -35,9 +37,6 @@ export async function nextTaskDirect(args, log) {
|
||||
};
|
||||
}
|
||||
|
||||
// Generate cache key using the provided task path
|
||||
const cacheKey = `nextTask:${tasksJsonPath}`;
|
||||
|
||||
// Define the action function to be executed on cache miss
|
||||
const coreNextTaskAction = async () => {
|
||||
try {
|
||||
@@ -59,8 +58,11 @@ export async function nextTaskDirect(args, log) {
|
||||
};
|
||||
}
|
||||
|
||||
// Read the complexity report
|
||||
const complexityReport = readComplexityReport(reportPath);
|
||||
|
||||
// Find the next task
|
||||
const nextTask = findNextTask(data.tasks);
|
||||
const nextTask = findNextTask(data.tasks, complexityReport);
|
||||
|
||||
if (!nextTask) {
|
||||
log.info(
|
||||
@@ -118,18 +120,11 @@ export async function nextTaskDirect(args, log) {
|
||||
|
||||
// Use the caching utility
|
||||
try {
|
||||
const result = await getCachedOrExecute({
|
||||
cacheKey,
|
||||
actionFn: coreNextTaskAction,
|
||||
log
|
||||
});
|
||||
log.info(`nextTaskDirect completed. From cache: ${result.fromCache}`);
|
||||
return result; // Returns { success, data/error, fromCache }
|
||||
const result = await coreNextTaskAction();
|
||||
log.info(`nextTaskDirect completed.`);
|
||||
return result;
|
||||
} catch (error) {
|
||||
// Catch unexpected errors from getCachedOrExecute itself
|
||||
log.error(
|
||||
`Unexpected error during getCachedOrExecute for nextTask: ${error.message}`
|
||||
);
|
||||
log.error(`Unexpected error during nextTask: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
|
||||
@@ -105,11 +105,9 @@ export async function parsePRDDirect(args, log, context = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
const useForce = force === true;
|
||||
const useAppend = append === true;
|
||||
if (useAppend) {
|
||||
if (append) {
|
||||
logWrapper.info('Append mode enabled.');
|
||||
if (useForce) {
|
||||
if (force) {
|
||||
logWrapper.warn(
|
||||
'Both --force and --append flags were provided. --force takes precedence; append mode will be ignored.'
|
||||
);
|
||||
@@ -117,7 +115,7 @@ export async function parsePRDDirect(args, log, context = {}) {
|
||||
}
|
||||
|
||||
logWrapper.info(
|
||||
`Parsing PRD via direct function. Input: ${inputPath}, Output: ${outputPath}, NumTasks: ${numTasks}, Force: ${useForce}, Append: ${useAppend}, ProjectRoot: ${projectRoot}`
|
||||
`Parsing PRD via direct function. Input: ${inputPath}, Output: ${outputPath}, NumTasks: ${numTasks}, Force: ${force}, Append: ${append}, ProjectRoot: ${projectRoot}`
|
||||
);
|
||||
|
||||
const wasSilent = isSilentMode();
|
||||
@@ -131,21 +129,28 @@ export async function parsePRDDirect(args, log, context = {}) {
|
||||
inputPath,
|
||||
outputPath,
|
||||
numTasks,
|
||||
{ session, mcpLog: logWrapper, projectRoot, useForce, useAppend },
|
||||
{
|
||||
session,
|
||||
mcpLog: logWrapper,
|
||||
projectRoot,
|
||||
force,
|
||||
append,
|
||||
commandName: 'parse-prd',
|
||||
outputType: 'mcp'
|
||||
},
|
||||
'json'
|
||||
);
|
||||
|
||||
// parsePRD returns { success: true, tasks: processedTasks } on success
|
||||
if (result && result.success && Array.isArray(result.tasks)) {
|
||||
logWrapper.success(
|
||||
`Successfully parsed PRD. Generated ${result.tasks.length} tasks.`
|
||||
);
|
||||
// Adjust check for the new return structure
|
||||
if (result && result.success) {
|
||||
const successMsg = `Successfully parsed PRD and generated tasks in ${result.tasksPath}`;
|
||||
logWrapper.success(successMsg);
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
message: `Successfully parsed PRD and generated ${result.tasks.length} tasks.`,
|
||||
outputPath: outputPath,
|
||||
taskCount: result.tasks.length
|
||||
message: successMsg,
|
||||
outputPath: result.tasksPath,
|
||||
telemetryData: result.telemetryData
|
||||
}
|
||||
};
|
||||
} else {
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
* Direct function implementation for showing task details
|
||||
*/
|
||||
|
||||
import { findTaskById, readJSON } from '../../../../scripts/modules/utils.js';
|
||||
import { getCachedOrExecute } from '../../tools/utils.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
findTaskById,
|
||||
readComplexityReport,
|
||||
readJSON
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { findTasksJsonPath } from '../utils/path-utils.js';
|
||||
|
||||
@@ -17,6 +16,7 @@ import { findTasksJsonPath } from '../utils/path-utils.js';
|
||||
* @param {Object} args - Command arguments.
|
||||
* @param {string} args.id - Task ID to show.
|
||||
* @param {string} [args.file] - Optional path to the tasks file (passed to findTasksJsonPath).
|
||||
* @param {string} args.reportPath - Explicit path to the complexity report file.
|
||||
* @param {string} [args.status] - Optional status to filter subtasks by.
|
||||
* @param {string} args.projectRoot - Absolute path to the project root directory (already normalized by tool).
|
||||
* @param {Object} log - Logger object.
|
||||
@@ -27,7 +27,7 @@ export async function showTaskDirect(args, log) {
|
||||
// Destructure session from context if needed later, otherwise ignore
|
||||
// const { session } = context;
|
||||
// Destructure projectRoot and other args. projectRoot is assumed normalized.
|
||||
const { id, file, status, projectRoot } = args;
|
||||
const { id, file, reportPath, status, projectRoot } = args;
|
||||
|
||||
log.info(
|
||||
`Showing task direct function. ID: ${id}, File: ${file}, Status Filter: ${status}, ProjectRoot: ${projectRoot}`
|
||||
@@ -64,9 +64,12 @@ export async function showTaskDirect(args, log) {
|
||||
};
|
||||
}
|
||||
|
||||
const complexityReport = readComplexityReport(reportPath);
|
||||
|
||||
const { task, originalSubtaskCount } = findTaskById(
|
||||
tasksData.tasks,
|
||||
id,
|
||||
complexityReport,
|
||||
status
|
||||
);
|
||||
|
||||
|
||||
@@ -108,18 +108,24 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
|
||||
try {
|
||||
// Execute core updateSubtaskById function
|
||||
const updatedSubtask = await updateSubtaskById(
|
||||
const coreResult = await updateSubtaskById(
|
||||
tasksPath,
|
||||
subtaskIdStr,
|
||||
prompt,
|
||||
useResearch,
|
||||
{ mcpLog: logWrapper, session, projectRoot },
|
||||
{
|
||||
mcpLog: logWrapper,
|
||||
session,
|
||||
projectRoot,
|
||||
commandName: 'update-subtask',
|
||||
outputType: 'mcp'
|
||||
},
|
||||
'json'
|
||||
);
|
||||
|
||||
if (updatedSubtask === null) {
|
||||
if (!coreResult || coreResult.updatedSubtask === null) {
|
||||
const message = `Subtask ${id} or its parent task not found.`;
|
||||
logWrapper.error(message); // Log as error since it couldn't be found
|
||||
logWrapper.error(message);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'SUBTASK_NOT_FOUND', message: message },
|
||||
@@ -136,9 +142,10 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
message: `Successfully updated subtask with ID ${subtaskIdStr}`,
|
||||
subtaskId: subtaskIdStr,
|
||||
parentId: subtaskIdStr.split('.')[0],
|
||||
subtask: updatedSubtask,
|
||||
subtask: coreResult.updatedSubtask,
|
||||
tasksPath,
|
||||
useResearch
|
||||
useResearch,
|
||||
telemetryData: coreResult.telemetryData
|
||||
},
|
||||
fromCache: false
|
||||
};
|
||||
|
||||
@@ -110,7 +110,7 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
|
||||
try {
|
||||
// Execute core updateTaskById function with proper parameters
|
||||
const updatedTask = await updateTaskById(
|
||||
const coreResult = await updateTaskById(
|
||||
tasksPath,
|
||||
taskId,
|
||||
prompt,
|
||||
@@ -118,19 +118,26 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
{
|
||||
mcpLog: logWrapper,
|
||||
session,
|
||||
projectRoot
|
||||
projectRoot,
|
||||
commandName: 'update-task',
|
||||
outputType: 'mcp'
|
||||
},
|
||||
'json'
|
||||
);
|
||||
|
||||
// Check if the core function indicated the task wasn't updated (e.g., status was 'done')
|
||||
if (updatedTask === null) {
|
||||
// Check if the core function returned null or an object without success
|
||||
if (!coreResult || coreResult.updatedTask === null) {
|
||||
// Core function logs the reason, just return success with info
|
||||
const message = `Task ${taskId} was not updated (likely already completed).`;
|
||||
logWrapper.info(message);
|
||||
return {
|
||||
success: true,
|
||||
data: { message: message, taskId: taskId, updated: false },
|
||||
data: {
|
||||
message: message,
|
||||
taskId: taskId,
|
||||
updated: false,
|
||||
telemetryData: coreResult?.telemetryData
|
||||
},
|
||||
fromCache: false
|
||||
};
|
||||
}
|
||||
@@ -146,7 +153,8 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
tasksPath: tasksPath,
|
||||
useResearch: useResearch,
|
||||
updated: true,
|
||||
updatedTask: updatedTask
|
||||
updatedTask: coreResult.updatedTask,
|
||||
telemetryData: coreResult.telemetryData
|
||||
},
|
||||
fromCache: false
|
||||
};
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
import path from 'path';
|
||||
import { updateTasks } from '../../../../scripts/modules/task-manager.js';
|
||||
import { createLogWrapper } from '../../tools/utils.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
|
||||
/**
|
||||
* Direct function wrapper for updating tasks based on new context.
|
||||
@@ -81,7 +85,6 @@ export async function updateTasksDirect(args, log, context = {}) {
|
||||
'json'
|
||||
);
|
||||
|
||||
// updateTasks returns { success: true, updatedTasks: [...] } on success
|
||||
if (result && result.success && Array.isArray(result.updatedTasks)) {
|
||||
logWrapper.success(
|
||||
`Successfully updated ${result.updatedTasks.length} tasks.`
|
||||
@@ -91,7 +94,8 @@ export async function updateTasksDirect(args, log, context = {}) {
|
||||
data: {
|
||||
message: `Successfully updated ${result.updatedTasks.length} tasks.`,
|
||||
tasksFile,
|
||||
updatedCount: result.updatedTasks.length
|
||||
updatedCount: result.updatedTasks.length,
|
||||
telemetryData: result.telemetryData
|
||||
}
|
||||
};
|
||||
} else {
|
||||
|
||||
@@ -339,6 +339,49 @@ export function findPRDDocumentPath(projectRoot, explicitPath, log) {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function findComplexityReportPath(projectRoot, explicitPath, log) {
|
||||
// If explicit path is provided, check if it exists
|
||||
if (explicitPath) {
|
||||
const fullPath = path.isAbsolute(explicitPath)
|
||||
? explicitPath
|
||||
: path.resolve(projectRoot, explicitPath);
|
||||
|
||||
if (fs.existsSync(fullPath)) {
|
||||
log.info(`Using provided PRD document path: ${fullPath}`);
|
||||
return fullPath;
|
||||
} else {
|
||||
log.warn(
|
||||
`Provided PRD document path not found: ${fullPath}, will search for alternatives`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Common locations and file patterns for PRD documents
|
||||
const commonLocations = [
|
||||
'', // Project root
|
||||
'scripts/'
|
||||
];
|
||||
|
||||
const commonFileNames = [
|
||||
'complexity-report.json',
|
||||
'task-complexity-report.json'
|
||||
];
|
||||
|
||||
// Check all possible combinations
|
||||
for (const location of commonLocations) {
|
||||
for (const fileName of commonFileNames) {
|
||||
const potentialPath = path.join(projectRoot, location, fileName);
|
||||
if (fs.existsSync(potentialPath)) {
|
||||
log.info(`Found PRD document at: ${potentialPath}`);
|
||||
return potentialPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.warn(`No PRD document found in common locations within ${projectRoot}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the tasks output directory path
|
||||
* @param {string} projectRoot - The project root directory
|
||||
|
||||
@@ -10,7 +10,10 @@ import {
|
||||
withNormalizedProjectRoot
|
||||
} from './utils.js';
|
||||
import { showTaskDirect } from '../core/task-master-core.js';
|
||||
import { findTasksJsonPath } from '../core/utils/path-utils.js';
|
||||
import {
|
||||
findTasksJsonPath,
|
||||
findComplexityReportPath
|
||||
} from '../core/utils/path-utils.js';
|
||||
|
||||
/**
|
||||
* Custom processor function that removes allTasks from the response
|
||||
@@ -50,6 +53,12 @@ export function registerShowTaskTool(server) {
|
||||
.string()
|
||||
.optional()
|
||||
.describe('Path to the tasks file relative to project root'),
|
||||
complexityReport: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
'Path to the complexity report file (relative to project root or absolute)'
|
||||
),
|
||||
projectRoot: z
|
||||
.string()
|
||||
.optional()
|
||||
@@ -81,9 +90,22 @@ export function registerShowTaskTool(server) {
|
||||
}
|
||||
|
||||
// Call the direct function, passing the normalized projectRoot
|
||||
// Resolve the path to complexity report
|
||||
let complexityReportPath;
|
||||
try {
|
||||
complexityReportPath = findComplexityReportPath(
|
||||
projectRoot,
|
||||
args.complexityReport,
|
||||
log
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(`Error finding complexity report: ${error.message}`);
|
||||
}
|
||||
const result = await showTaskDirect(
|
||||
{
|
||||
tasksJsonPath: tasksJsonPath,
|
||||
reportPath: complexityReportPath,
|
||||
// Pass other relevant args
|
||||
id: id,
|
||||
status: status,
|
||||
projectRoot: projectRoot
|
||||
|
||||
@@ -10,7 +10,10 @@ import {
|
||||
withNormalizedProjectRoot
|
||||
} from './utils.js';
|
||||
import { listTasksDirect } from '../core/task-master-core.js';
|
||||
import { findTasksJsonPath } from '../core/utils/path-utils.js';
|
||||
import {
|
||||
findTasksJsonPath,
|
||||
findComplexityReportPath
|
||||
} from '../core/utils/path-utils.js';
|
||||
|
||||
/**
|
||||
* Register the getTasks tool with the MCP server
|
||||
@@ -38,6 +41,12 @@ export function registerListTasksTool(server) {
|
||||
.describe(
|
||||
'Path to the tasks file (relative to project root or absolute)'
|
||||
),
|
||||
complexityReport: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
'Path to the complexity report file (relative to project root or absolute)'
|
||||
),
|
||||
projectRoot: z
|
||||
.string()
|
||||
.describe('The directory of the project. Must be an absolute path.')
|
||||
@@ -60,11 +69,23 @@ export function registerListTasksTool(server) {
|
||||
);
|
||||
}
|
||||
|
||||
// Resolve the path to complexity report
|
||||
let complexityReportPath;
|
||||
try {
|
||||
complexityReportPath = findComplexityReportPath(
|
||||
args.projectRoot,
|
||||
args.complexityReport,
|
||||
log
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(`Error finding complexity report: ${error.message}`);
|
||||
}
|
||||
const result = await listTasksDirect(
|
||||
{
|
||||
tasksJsonPath: tasksJsonPath,
|
||||
status: args.status,
|
||||
withSubtasks: args.withSubtasks
|
||||
withSubtasks: args.withSubtasks,
|
||||
reportPath: complexityReportPath
|
||||
},
|
||||
log
|
||||
);
|
||||
|
||||
@@ -10,7 +10,10 @@ import {
|
||||
withNormalizedProjectRoot
|
||||
} from './utils.js';
|
||||
import { nextTaskDirect } from '../core/task-master-core.js';
|
||||
import { findTasksJsonPath } from '../core/utils/path-utils.js';
|
||||
import {
|
||||
findTasksJsonPath,
|
||||
findComplexityReportPath
|
||||
} from '../core/utils/path-utils.js';
|
||||
|
||||
/**
|
||||
* Register the next-task tool with the MCP server
|
||||
@@ -23,6 +26,12 @@ export function registerNextTaskTool(server) {
|
||||
'Find the next task to work on based on dependencies and status',
|
||||
parameters: z.object({
|
||||
file: z.string().optional().describe('Absolute path to the tasks file'),
|
||||
complexityReport: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
'Path to the complexity report file (relative to project root or absolute)'
|
||||
),
|
||||
projectRoot: z
|
||||
.string()
|
||||
.describe('The directory of the project. Must be an absolute path.')
|
||||
@@ -45,9 +54,21 @@ export function registerNextTaskTool(server) {
|
||||
);
|
||||
}
|
||||
|
||||
// Resolve the path to complexity report
|
||||
let complexityReportPath;
|
||||
try {
|
||||
complexityReportPath = findComplexityReportPath(
|
||||
args.projectRoot,
|
||||
args.complexityReport,
|
||||
log
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(`Error finding complexity report: ${error.message}`);
|
||||
}
|
||||
const result = await nextTaskDirect(
|
||||
{
|
||||
tasksJsonPath: tasksJsonPath
|
||||
tasksJsonPath: tasksJsonPath,
|
||||
reportPath: complexityReportPath
|
||||
},
|
||||
log
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from './utils.js';
|
||||
import { setTaskStatusDirect } from '../core/task-master-core.js';
|
||||
import { findTasksJsonPath } from '../core/utils/path-utils.js';
|
||||
import { TASK_STATUS_OPTIONS } from '../../../src/constants/task-status.js';
|
||||
|
||||
/**
|
||||
* Register the setTaskStatus tool with the MCP server
|
||||
@@ -27,7 +28,7 @@ export function registerSetTaskStatusTool(server) {
|
||||
"Task ID or subtask ID (e.g., '15', '15.2'). Can be comma-separated to update multiple tasks/subtasks at once."
|
||||
),
|
||||
status: z
|
||||
.string()
|
||||
.enum(TASK_STATUS_OPTIONS)
|
||||
.describe(
|
||||
"New status to set (e.g., 'pending', 'done', 'in-progress', 'review', 'deferred', 'cancelled'."
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user