mirror of
https://github.com/eyaltoledano/claude-task-master.git
synced 2026-01-30 06:12:05 +00:00
chore: apply requested changes
This commit is contained in:
@@ -26,8 +26,7 @@ export function registerAutopilotResumeTool(server: FastMCP) {
|
|||||||
'Resume a previously started TDD workflow from saved state. Restores the workflow state machine and continues from where it left off.',
|
'Resume a previously started TDD workflow from saved state. Restores the workflow state machine and continues from where it left off.',
|
||||||
parameters: ResumeWorkflowSchema,
|
parameters: ResumeWorkflowSchema,
|
||||||
annotations: {
|
annotations: {
|
||||||
title: 'Resume Autopilot Workflow',
|
title: 'Resume Autopilot Workflow'
|
||||||
readOnlyHint: false
|
|
||||||
},
|
},
|
||||||
execute: withToolContext(
|
execute: withToolContext(
|
||||||
'autopilot-resume',
|
'autopilot-resume',
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { getPromptManager } from '../prompt-manager.js';
|
|||||||
import { findProjectRoot, flattenTasksWithSubtasks } from '../utils.js';
|
import { findProjectRoot, flattenTasksWithSubtasks } from '../utils.js';
|
||||||
import { ContextGatherer } from '../utils/contextGatherer.js';
|
import { ContextGatherer } from '../utils/contextGatherer.js';
|
||||||
import { FuzzyTaskSearch } from '../utils/fuzzyTaskSearch.js';
|
import { FuzzyTaskSearch } from '../utils/fuzzyTaskSearch.js';
|
||||||
|
import { normalizeSubtask } from './parse-prd/parse-prd-helpers.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expand a task into subtasks using the unified AI service (generateObjectService).
|
* Expand a task into subtasks using the unified AI service (generateObjectService).
|
||||||
@@ -331,12 +332,9 @@ async function expandTask(
|
|||||||
if (!mainResult || !Array.isArray(mainResult.subtasks)) {
|
if (!mainResult || !Array.isArray(mainResult.subtasks)) {
|
||||||
throw new Error('AI response did not include a valid subtasks array.');
|
throw new Error('AI response did not include a valid subtasks array.');
|
||||||
}
|
}
|
||||||
generatedSubtasks = mainResult.subtasks.map((subtask) => ({
|
generatedSubtasks = mainResult.subtasks.map((subtask) =>
|
||||||
...subtask,
|
normalizeSubtask(subtask)
|
||||||
dependencies: subtask.dependencies ?? [],
|
);
|
||||||
status: subtask.status ?? 'pending',
|
|
||||||
testStrategy: subtask.testStrategy ?? null
|
|
||||||
}));
|
|
||||||
logger.info(`Received ${generatedSubtasks.length} subtasks from AI.`);
|
logger.info(`Received ${generatedSubtasks.length} subtasks from AI.`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (loadingIndicator) stopLoadingIndicator(loadingIndicator);
|
if (loadingIndicator) stopLoadingIndicator(loadingIndicator);
|
||||||
|
|||||||
@@ -23,6 +23,57 @@ export function estimateTokens(text) {
|
|||||||
return Math.ceil(text.length / 4);
|
return Math.ceil(text.length / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a subtask by applying schema defaults for missing fields
|
||||||
|
* Subtasks have: id, title, description, status, dependencies, details
|
||||||
|
* (no testStrategy, no priority - those are task-only fields)
|
||||||
|
* @param {Object} subtask - Raw subtask object from AI response
|
||||||
|
* @returns {Object} Subtask with all required fields populated
|
||||||
|
*/
|
||||||
|
export function normalizeSubtask(subtask) {
|
||||||
|
return {
|
||||||
|
...subtask,
|
||||||
|
title: subtask.title ?? '',
|
||||||
|
description: subtask.description ?? '',
|
||||||
|
details: subtask.details ?? '',
|
||||||
|
dependencies: subtask.dependencies ?? [],
|
||||||
|
status: subtask.status ?? 'pending'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a task by applying schema defaults for missing fields
|
||||||
|
* @param {Object} task - Raw task object from AI response
|
||||||
|
* @param {string} defaultPriority - Default priority to use
|
||||||
|
* @returns {Object} Task with all required fields populated
|
||||||
|
*/
|
||||||
|
export function normalizeTask(task, defaultPriority = 'medium') {
|
||||||
|
return {
|
||||||
|
...task,
|
||||||
|
status: task.status ?? 'pending',
|
||||||
|
title: task.title ?? '',
|
||||||
|
description: task.description ?? '',
|
||||||
|
dependencies: task.dependencies ?? [],
|
||||||
|
priority: task.priority ?? defaultPriority,
|
||||||
|
details: task.details ?? '',
|
||||||
|
testStrategy: task.testStrategy ?? '',
|
||||||
|
subtasks: task.subtasks
|
||||||
|
? task.subtasks.map((subtask) => normalizeSubtask(subtask))
|
||||||
|
: undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize an array of tasks by applying schema defaults
|
||||||
|
* @param {Array} tasks - Array of raw task objects
|
||||||
|
* @param {string} defaultPriority - Default priority to use
|
||||||
|
* @returns {Array} Tasks with all required fields populated
|
||||||
|
*/
|
||||||
|
export function normalizeTasks(tasks, defaultPriority = 'medium') {
|
||||||
|
if (!Array.isArray(tasks)) return [];
|
||||||
|
return tasks.map((task) => normalizeTask(task, defaultPriority));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read and validate PRD content
|
* Read and validate PRD content
|
||||||
* @param {string} prdPath - Path to PRD file
|
* @param {string} prdPath - Path to PRD file
|
||||||
@@ -139,23 +190,17 @@ export function processTasks(
|
|||||||
let currentId = startId;
|
let currentId = startId;
|
||||||
const taskMap = new Map();
|
const taskMap = new Map();
|
||||||
|
|
||||||
// First pass: assign new IDs and create mapping
|
// First pass: normalize, assign new IDs, and create mapping
|
||||||
const processedTasks = rawTasks.map((task) => {
|
const processedTasks = rawTasks.map((task) => {
|
||||||
const newId = currentId++;
|
const newId = currentId++;
|
||||||
taskMap.set(task.id, newId);
|
taskMap.set(task.id, newId);
|
||||||
|
|
||||||
|
// Apply schema defaults via normalizeTask, then override with new ID
|
||||||
|
const normalized = normalizeTask(task, defaultPriority);
|
||||||
return {
|
return {
|
||||||
...task,
|
...normalized,
|
||||||
id: newId,
|
id: newId,
|
||||||
status: task.status || 'pending',
|
subtasks: normalized.subtasks || []
|
||||||
priority: task.priority || defaultPriority,
|
|
||||||
dependencies: Array.isArray(task.dependencies) ? task.dependencies : [],
|
|
||||||
subtasks: task.subtasks || [],
|
|
||||||
// Ensure all required fields have values
|
|
||||||
title: task.title || '',
|
|
||||||
description: task.description || '',
|
|
||||||
details: task.details || '',
|
|
||||||
testStrategy: task.testStrategy || ''
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ export async function handleNonStreamingService(config, prompts) {
|
|||||||
spinner.succeed('Tasks generated successfully!');
|
spinner.succeed('Tasks generated successfully!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: Schema defaults are applied later by processTasks in parsePRDCore
|
||||||
return {
|
return {
|
||||||
parsedTasks: generatedData.tasks,
|
parsedTasks: generatedData.tasks,
|
||||||
aiServiceResponse,
|
aiServiceResponse,
|
||||||
|
|||||||
@@ -460,6 +460,7 @@ async function finalizeStreamingResults(state, context) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: Schema defaults are applied later by processTasks in parsePRDCore
|
||||||
return {
|
return {
|
||||||
parsedTasks: lastPartialObject.tasks,
|
parsedTasks: lastPartialObject.tasks,
|
||||||
estimatedOutputTokens: finalOutputTokens,
|
estimatedOutputTokens: finalOutputTokens,
|
||||||
@@ -570,19 +571,7 @@ async function processWithGenerateObject(context, logger) {
|
|||||||
// Extract tasks from the result (handle both direct tasks and mainResult.tasks)
|
// Extract tasks from the result (handle both direct tasks and mainResult.tasks)
|
||||||
const tasks = result?.mainResult || result;
|
const tasks = result?.mainResult || result;
|
||||||
|
|
||||||
// Apply defaults to ensure all required fields are present
|
// Note: Schema defaults are applied later by processTasks in parsePRDCore
|
||||||
if (tasks && Array.isArray(tasks.tasks)) {
|
|
||||||
tasks.tasks = tasks.tasks.map((task) => ({
|
|
||||||
...task,
|
|
||||||
status: task.status ?? 'pending',
|
|
||||||
title: task.title ?? '',
|
|
||||||
description: task.description ?? '',
|
|
||||||
dependencies: task.dependencies ?? [],
|
|
||||||
priority: task.priority ?? context.defaultPriority ?? 'medium',
|
|
||||||
details: task.details ?? '',
|
|
||||||
testStrategy: task.testStrategy ?? ''
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the generated tasks
|
// Process the generated tasks
|
||||||
if (tasks && Array.isArray(tasks.tasks)) {
|
if (tasks && Array.isArray(tasks.tasks)) {
|
||||||
|
|||||||
@@ -1,15 +1,8 @@
|
|||||||
import path from 'path';
|
|
||||||
import boxen from 'boxen';
|
import boxen from 'boxen';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import Table from 'cli-table3';
|
import Table from 'cli-table3';
|
||||||
|
|
||||||
import {
|
import { log as consoleLog, readJSON, truncate, writeJSON } from '../utils.js';
|
||||||
log as consoleLog,
|
|
||||||
isSilentMode,
|
|
||||||
readJSON,
|
|
||||||
truncate,
|
|
||||||
writeJSON
|
|
||||||
} from '../utils.js';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
displayAiUsageSummary,
|
displayAiUsageSummary,
|
||||||
@@ -29,7 +22,7 @@ import { getPromptManager } from '../prompt-manager.js';
|
|||||||
import { findProjectRoot, flattenTasksWithSubtasks } from '../utils.js';
|
import { findProjectRoot, flattenTasksWithSubtasks } from '../utils.js';
|
||||||
import { ContextGatherer } from '../utils/contextGatherer.js';
|
import { ContextGatherer } from '../utils/contextGatherer.js';
|
||||||
import { FuzzyTaskSearch } from '../utils/fuzzyTaskSearch.js';
|
import { FuzzyTaskSearch } from '../utils/fuzzyTaskSearch.js';
|
||||||
import { getModelConfiguration } from './models.js';
|
import { normalizeTasks } from './parse-prd/parse-prd-helpers.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update tasks based on new context using the unified AI service.
|
* Update tasks based on new context using the unified AI service.
|
||||||
@@ -233,25 +226,9 @@ async function updateTasks(
|
|||||||
|
|
||||||
// With generateObject, we get structured data directly
|
// With generateObject, we get structured data directly
|
||||||
const defaultPriority = getDefaultPriority(projectRoot) ?? 'medium';
|
const defaultPriority = getDefaultPriority(projectRoot) ?? 'medium';
|
||||||
const parsedUpdatedTasks = aiServiceResponse.mainResult.tasks.map(
|
const parsedUpdatedTasks = normalizeTasks(
|
||||||
(task) => ({
|
aiServiceResponse.mainResult.tasks,
|
||||||
...task,
|
defaultPriority
|
||||||
status: task.status ?? 'pending',
|
|
||||||
title: task.title ?? '',
|
|
||||||
description: task.description ?? '',
|
|
||||||
dependencies: task.dependencies ?? [],
|
|
||||||
priority: task.priority ?? defaultPriority,
|
|
||||||
details: task.details ?? '',
|
|
||||||
testStrategy: task.testStrategy ?? '',
|
|
||||||
subtasks: task.subtasks
|
|
||||||
? task.subtasks.map((subtask) => ({
|
|
||||||
...subtask,
|
|
||||||
dependencies: subtask.dependencies ?? [],
|
|
||||||
status: subtask.status ?? 'pending',
|
|
||||||
testStrategy: subtask.testStrategy ?? ''
|
|
||||||
}))
|
|
||||||
: null
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// --- Update Tasks Data (Updated writeJSON call) ---
|
// --- Update Tasks Data (Updated writeJSON call) ---
|
||||||
|
|||||||
Reference in New Issue
Block a user