fix(ai-validation): comprehensive fixes for AI response validation issues
- Fix update command validation when AI omits subtasks/status/dependencies - Fix add-task command when AI returns non-string details field - Fix update-task command when AI subtasks miss required fields - Add preprocessing to ensure proper field types before validation - Prevent split() errors on non-string fields - Set proper defaults for missing required fields
This commit is contained in:
@@ -190,8 +190,25 @@ function parseUpdatedTaskFromText(text, expectedTaskId, logFn, isMCP) {
|
|||||||
throw new Error('Parsed AI response is not a valid JSON object.');
|
throw new Error('Parsed AI response is not a valid JSON object.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Preprocess the task to ensure subtasks have proper structure
|
||||||
|
const preprocessedTask = {
|
||||||
|
...parsedTask,
|
||||||
|
// Ensure subtasks is an array and each subtask has required fields
|
||||||
|
subtasks: Array.isArray(parsedTask.subtasks)
|
||||||
|
? parsedTask.subtasks.map(subtask => ({
|
||||||
|
...subtask,
|
||||||
|
title: subtask.title || '',
|
||||||
|
description: subtask.description || '',
|
||||||
|
status: subtask.status || 'pending',
|
||||||
|
dependencies: Array.isArray(subtask.dependencies) ? subtask.dependencies : [],
|
||||||
|
details: typeof subtask.details === 'string' ? subtask.details : String(subtask.details || ''),
|
||||||
|
testStrategy: typeof subtask.testStrategy === 'string' ? subtask.testStrategy : String(subtask.testStrategy || '')
|
||||||
|
}))
|
||||||
|
: []
|
||||||
|
};
|
||||||
|
|
||||||
// Validate the parsed task object using Zod
|
// Validate the parsed task object using Zod
|
||||||
const validationResult = updatedTaskSchema.safeParse(parsedTask);
|
const validationResult = updatedTaskSchema.safeParse(preprocessedTask);
|
||||||
if (!validationResult.success) {
|
if (!validationResult.success) {
|
||||||
report('error', 'Parsed task object failed Zod validation.');
|
report('error', 'Parsed task object failed Zod validation.');
|
||||||
validationResult.error.errors.forEach((err) => {
|
validationResult.error.errors.forEach((err) => {
|
||||||
|
|||||||
@@ -196,7 +196,18 @@ function parseUpdatedTasksFromText(text, expectedCount, logFn, isMCP) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const validationResult = updatedTaskArraySchema.safeParse(parsedTasks);
|
// Preprocess tasks to ensure required fields have proper defaults
|
||||||
|
const preprocessedTasks = parsedTasks.map(task => ({
|
||||||
|
...task,
|
||||||
|
// Ensure subtasks is always an array (not null or undefined)
|
||||||
|
subtasks: Array.isArray(task.subtasks) ? task.subtasks : [],
|
||||||
|
// Ensure status has a default value if missing
|
||||||
|
status: task.status || 'pending',
|
||||||
|
// Ensure dependencies is always an array
|
||||||
|
dependencies: Array.isArray(task.dependencies) ? task.dependencies : []
|
||||||
|
}));
|
||||||
|
|
||||||
|
const validationResult = updatedTaskArraySchema.safeParse(preprocessedTasks);
|
||||||
if (!validationResult.success) {
|
if (!validationResult.success) {
|
||||||
report('error', 'Parsed task array failed Zod validation.');
|
report('error', 'Parsed task array failed Zod validation.');
|
||||||
validationResult.error.errors.forEach((err) => {
|
validationResult.error.errors.forEach((err) => {
|
||||||
@@ -442,7 +453,14 @@ async function updateTasks(
|
|||||||
data.tasks.forEach((task, index) => {
|
data.tasks.forEach((task, index) => {
|
||||||
if (updatedTasksMap.has(task.id)) {
|
if (updatedTasksMap.has(task.id)) {
|
||||||
// Only update if the task was part of the set sent to AI
|
// Only update if the task was part of the set sent to AI
|
||||||
data.tasks[index] = updatedTasksMap.get(task.id);
|
const updatedTask = updatedTasksMap.get(task.id);
|
||||||
|
// Merge the updated task with the existing one to preserve fields like subtasks
|
||||||
|
data.tasks[index] = {
|
||||||
|
...task, // Keep all existing fields
|
||||||
|
...updatedTask, // Override with updated fields
|
||||||
|
// Ensure subtasks field is preserved if not provided by AI
|
||||||
|
subtasks: updatedTask.subtasks !== undefined ? updatedTask.subtasks : task.subtasks
|
||||||
|
};
|
||||||
actualUpdateCount++;
|
actualUpdateCount++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user