UNPKG

openai-compatible-task-master

Version:

使用MCP解析PRD文档并生成任务列表

165 lines (162 loc) 6.34 kB
import * as fs from 'fs'; import * as path from 'path'; /** * 递归查找任务 * @param tasks 任务列表 * @param targetId 目标任务ID * @returns 找到的任务及其父任务链 */ function findTaskWithParentChain(tasks, targetId) { function findInTasks(tasks, parentChain = []) { for (const task of tasks) { // 检查当前任务 if (String(task.id) === targetId) { return { task, parentChain }; } // 检查子任务 if (task.subTasks) { for (const subTask of task.subTasks) { if (String(subTask.id) === targetId) { return { task: subTask, parentChain: [task, ...parentChain] }; } // 递归检查更深层的子任务 const result = findInTasks(subTask.subTasks || [], [task, ...parentChain]); if (result.task) { return result; } } } } return { task: null, parentChain: [] }; } return findInTasks(tasks); } /** * 检查所有子任务是否完成 * @param task 任务 * @returns 是否所有子任务已完成 * @internal */ // eslint-disable-next-line @typescript-eslint/no-unused-vars function areAllSubTasksDone(task) { if (!task.subTasks || task.subTasks.length === 0) { return true; } return task.subTasks.every(subTask => { if (subTask.status !== 'done') { return false; } return areAllSubTasksDone(subTask); }); } /** * 检查父任务链中是否有已完成的任务 * @param tasks 任务列表 * @param taskId 任务ID * @returns 是否存在已完成的父任务 * @internal */ // eslint-disable-next-line @typescript-eslint/no-unused-vars function hasCompletedParent(tasks, taskId) { const parts = taskId.split('.'); if (parts.length <= 1) return false; // 构建父任务ID const parentId = parts.slice(0, -1).join('.'); const { task: parentTask } = findTaskWithParentChain(tasks, parentId); if (!parentTask) return false; return parentTask.status === 'done'; } /** * 设置任务状态 * @param projectDir 项目根目录 * @param tasksPath 任务文件路径 * @param taskId 要更新的任务ID * @param status 新状态 * @param completionSummary 完成总结(仅在status为done时有效) * @returns 包含操作结果的对象 */ export async function setTaskStatus(projectDir, tasksPath, taskId, status, completionSummary) { // 验证状态值 if (!['pending', 'in-progress', 'done'].includes(status)) { return { saved: false, message: '无效的状态值。必须是 pending、in-progress 或 done 之一' }; } // 验证completionSummary if (status === 'done' && !completionSummary) { return { saved: false, message: `当状态设置为done时,必须使用--summary参数提供完成总结。 如何写好完成总结: 1. 简明扼要地描述已实现的功能和解决的问题 2. 提及重要的实现细节和采用的技术方案 3. 指出任何潜在的限制或需要注意的事项 4. 如有适用,提及后续可能的优化方向 示例:--summary "实现了用户认证功能,包括登录、注册和密码重置。采用JWT进行身份验证,使用bcrypt加密密码。添加了必要的输入验证和错误处理。" 命令示例: npx octm-cli set-status --task-id ${taskId} --status done --summary "实现了任务要求的功能,包括...,解决了...的问题"` }; } try { // 构建完整的任务文件路径 const fullTasksPath = path.resolve(projectDir, tasksPath); // 检查任务文件是否存在 if (!fs.existsSync(fullTasksPath)) { throw new Error(`任务文件不存在: ${fullTasksPath}`); } // 读取任务文件 const tasksContent = fs.readFileSync(fullTasksPath, 'utf8'); const tasksData = JSON.parse(tasksContent); // 查找要更新的任务 let taskFound = false; const updateTaskStatus = (tasks) => { for (const task of tasks) { // 检查当前任务是否匹配 if (task.id === taskId) { // 如果任务已经完成,不允许更改状态 if (task.status === 'done' && status !== 'done') { return false; } // 更新任务状态 task.status = status; // 如果状态是done,设置完成总结;否则清除完成总结 if (status === 'done') { task.completionSummary = completionSummary; } else if (task.completionSummary) { // 如果状态不是done但存在完成总结,清除它 delete task.completionSummary; } taskFound = true; return true; } // 递归检查子任务 if (task.subTasks && task.subTasks.length > 0) { const subtaskUpdated = updateTaskStatus(task.subTasks); if (subtaskUpdated) { return true; } } } return false; }; // 尝试更新任务状态 const updated = updateTaskStatus(tasksData.tasks); if (!taskFound) { return { saved: false, message: `未找到ID为 ${taskId} 的任务` }; } if (!updated) { return { saved: false, message: '无法更新任务状态。已完成的任务不能更改为其他状态' }; } // 保存更新后的任务文件 fs.writeFileSync(fullTasksPath, JSON.stringify(tasksData, null, 2)); return { saved: true, message: `已将任务 ${taskId} 的状态更新为 ${status}${status === 'done' ? ',并添加了完成总结' : ''}` }; } catch (error) { throw new Error(`更新任务状态时出错: ${error.message}`); } } //# sourceMappingURL=set_status.js.map