fix(update-task): pass projectRoot and adjust parsing

Modified update-task-by-id core, direct function, and tool to pass projectRoot. Reverted parsing logic in core function to prioritize `{...}` extraction, resolving parsing errors. Fixed ReferenceError by correctly destructuring projectRoot.
This commit is contained in:
Eyal Toledano
2025-05-01 17:46:33 -04:00
parent ad1c234b4e
commit 1862ca2360
6 changed files with 248 additions and 131 deletions

View File

@@ -43,13 +43,12 @@ const updatedTaskArraySchema = z.array(updatedTaskSchema);
* Parses an array of task objects from AI's text response.
* @param {string} text - Response text from AI.
* @param {number} expectedCount - Expected number of tasks.
* @param {Function | Object} logFn - The logging function (consoleLog) or MCP log object.
* @param {Function | Object} logFn - The logging function or MCP log object.
* @param {boolean} isMCP - Flag indicating if logFn is MCP logger.
* @returns {Array} Parsed and validated tasks array.
* @throws {Error} If parsing or validation fails.
*/
function parseUpdatedTasksFromText(text, expectedCount, logFn, isMCP) {
// Helper for consistent logging inside parser
const report = (level, ...args) => {
if (isMCP) {
if (typeof logFn[level] === 'function') logFn[level](...args);
@@ -70,32 +69,70 @@ function parseUpdatedTasksFromText(text, expectedCount, logFn, isMCP) {
let cleanedResponse = text.trim();
const originalResponseForDebug = cleanedResponse;
// Extract from Markdown code block first
// Step 1: Attempt to extract from Markdown code block first
const codeBlockMatch = cleanedResponse.match(
/```(?:json)?\s*([\s\S]*?)\s*```/
/```(?:json|javascript)?\s*([\s\S]*?)\s*```/i // Made case-insensitive, allow js
);
if (codeBlockMatch) {
cleanedResponse = codeBlockMatch[1].trim();
report('info', 'Extracted JSON content from Markdown code block.');
report('info', 'Extracted content from Markdown code block.');
} else {
// If no code block, find first '[' and last ']' for the array
// Step 2 (if no code block): Attempt to strip common language identifiers/intro text
// List common prefixes AI might add before JSON
const commonPrefixes = [
'json\n',
'javascript\n',
'python\n', // Language identifiers
'here are the updated tasks:',
'here is the updated json:', // Common intro phrases
'updated tasks:',
'updated json:',
'response:',
'output:'
];
let prefixFound = false;
for (const prefix of commonPrefixes) {
if (cleanedResponse.toLowerCase().startsWith(prefix)) {
cleanedResponse = cleanedResponse.substring(prefix.length).trim();
report('info', `Stripped prefix: "${prefix.trim()}"`);
prefixFound = true;
break; // Stop after finding the first matching prefix
}
}
// Step 3 (if no code block and no prefix stripped, or after stripping): Find first '[' and last ']'
// This helps if there's still leading/trailing text around the array
const firstBracket = cleanedResponse.indexOf('[');
const lastBracket = cleanedResponse.lastIndexOf(']');
if (firstBracket !== -1 && lastBracket > firstBracket) {
cleanedResponse = cleanedResponse.substring(
const extractedArray = cleanedResponse.substring(
firstBracket,
lastBracket + 1
);
report('info', 'Extracted content between first [ and last ].');
} else {
// Basic check to see if the extraction looks like JSON
if (extractedArray.length > 2) {
// More than just '[]'
cleanedResponse = extractedArray; // Use the extracted array content
if (!codeBlockMatch && !prefixFound) {
// Only log if we didn't already log extraction/stripping
report('info', 'Extracted content between first [ and last ].');
}
} else if (!codeBlockMatch && !prefixFound) {
report(
'warn',
'Found brackets "[]" but content seems empty or invalid. Proceeding with original cleaned response.'
);
}
} else if (!codeBlockMatch && !prefixFound) {
// Only warn if no other extraction method worked
report(
'warn',
'Response does not appear to contain a JSON array structure. Parsing raw response.'
'Response does not appear to contain a JSON code block, known prefix, or clear array structure ([...]). Attempting to parse raw response.'
);
}
}
// Attempt to parse the array
// Step 4: Attempt to parse the (hopefully) cleaned JSON array
let parsedTasks;
try {
parsedTasks = JSON.parse(cleanedResponse);
@@ -114,7 +151,7 @@ function parseUpdatedTasksFromText(text, expectedCount, logFn, isMCP) {
);
}
// Validate Array structure
// Step 5: Validate Array structure
if (!Array.isArray(parsedTasks)) {
report(
'error',
@@ -135,7 +172,7 @@ function parseUpdatedTasksFromText(text, expectedCount, logFn, isMCP) {
);
}
// Validate each task object using Zod
// Step 6: Validate each task object using Zod
const validationResult = updatedTaskArraySchema.safeParse(parsedTasks);
if (!validationResult.success) {
report('error', 'Parsed task array failed Zod validation.');