task-processor.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /**
  2. * 任务处理模块
  3. *
  4. * 负责处理单个任务,将任务描述发送给Cursor执行代码开发
  5. */
  6. import { info, error } from './logger.js';
  7. /**
  8. * 处理任务
  9. *
  10. * 这个函数将任务描述格式化后返回,供Cursor通过MCP协议接收并执行
  11. *
  12. * @param {Object} task - 任务对象
  13. * @param {number} task.task_id - 任务ID
  14. * @param {string} task.task_name - 任务名称
  15. * @param {string} task.task_description - 任务描述(markdown格式)
  16. * @param {boolean} autoComplete - 是否启用自动完成模式
  17. * @returns {Promise<Object>} 处理结果
  18. */
  19. export async function processTask(task, autoComplete = true) {
  20. info(`[Task Processor] Processing task ${task.task_id}: ${task.task_name} (autoComplete: ${autoComplete})`);
  21. const startTime = Date.now();
  22. try {
  23. // 构建任务执行消息
  24. // 这个消息将通过MCP协议返回给Cursor,Cursor会解析并执行
  25. const taskMessage = {
  26. type: 'development_task',
  27. task_id: task.task_id,
  28. task_name: task.task_name,
  29. description: task.task_description,
  30. timestamp: new Date().toISOString(),
  31. auto_complete: autoComplete,
  32. };
  33. // 格式化任务描述,确保是有效的markdown
  34. const formattedDescription = formatTaskDescription(task);
  35. info(`[Task Processor] Task ${task.task_id} description formatted successfully (${formattedDescription.length} characters)`);
  36. // 从任务描述中提取关键信息
  37. const extractedInfo = extractTaskInfo(task);
  38. // 返回任务信息,供Cursor处理
  39. // Cursor会接收到这个信息,并根据描述执行代码开发
  40. const result = {
  41. success: true,
  42. message: `Task ${task.task_id} prepared for execution`,
  43. task_id: task.task_id,
  44. task_name: task.task_name,
  45. formatted_description: formattedDescription,
  46. auto_complete: autoComplete,
  47. // 这些字段将在任务完成后更新到数据库
  48. code_name: extractedInfo.code_name || null,
  49. code_path: extractedInfo.code_path || task.code_path || 'app/core/data_flow',
  50. execution_instructions: autoComplete ?
  51. buildAutoCompleteInstructions(task, formattedDescription) :
  52. buildManualInstructions(task, formattedDescription),
  53. };
  54. const duration = Date.now() - startTime;
  55. info(`[Task Processor] Task ${task.task_id} processed successfully in ${duration}ms`);
  56. return result;
  57. } catch (err) {
  58. const duration = Date.now() - startTime;
  59. error(`[Task Processor] Task ${task.task_id} processing failed after ${duration}ms: ${err.message}`);
  60. return {
  61. success: false,
  62. message: `Failed to process task: ${err.message}`,
  63. error: err.stack,
  64. };
  65. }
  66. }
  67. /**
  68. * 构建自动完成模式的执行指令
  69. *
  70. * @param {Object} task - 任务对象
  71. * @param {string} formattedDescription - 格式化后的任务描述
  72. * @returns {string} 执行指令
  73. */
  74. function buildAutoCompleteInstructions(task, formattedDescription) {
  75. return `
  76. 🤖 自动执行模式 - 任务 ${task.task_id}
  77. ## 📋 任务信息
  78. - **任务ID**: ${task.task_id}
  79. - **任务名称**: ${task.task_name}
  80. ## 📝 任务描述
  81. ${formattedDescription}
  82. ## 🚀 自动执行步骤
  83. **请按照以下步骤自动完成任务:**
  84. ### 1️⃣ 分析需求
  85. 仔细阅读任务描述,理解功能要求和技术细节。
  86. ### 2️⃣ 生成代码
  87. 根据任务描述,创建 Python 代码文件:
  88. - 确保代码结构清晰、注释完整
  89. - 遵循项目代码规范(PEP 8)
  90. - 包含必要的错误处理和日志记录
  91. - 如果任务描述中指定了文件路径,请使用该路径
  92. - 否则默认保存到 \`app/core/data_flow/\` 目录
  93. ### 3️⃣ 自动更新任务状态
  94. **重要!代码生成完成后,必须调用以下 MCP 工具更新任务状态:**
  95. \`\`\`
  96. 工具: update_task_status
  97. 参数: {
  98. "task_id": ${task.task_id},
  99. "status": "completed",
  100. "code_name": "<生成的代码文件名>.py",
  101. "code_path": "<代码文件的目录路径>"
  102. }
  103. \`\`\`
  104. ### 示例
  105. 如果生成了文件 \`app/core/data_flow/data_processor.py\`,则调用:
  106. \`\`\`
  107. {
  108. "task_id": ${task.task_id},
  109. "status": "completed",
  110. "code_name": "data_processor.py",
  111. "code_path": "app/core/data_flow"
  112. }
  113. \`\`\`
  114. ---
  115. **⚠️ 执行提醒**:
  116. - 不要跳过任何步骤
  117. - 必须在生成代码后立即更新任务状态
  118. - 如果遇到问题,将 status 设为 "failed" 并记录原因
  119. `;
  120. }
  121. /**
  122. * 构建手动模式的执行指令
  123. *
  124. * @param {Object} task - 任务对象
  125. * @param {string} formattedDescription - 格式化后的任务描述
  126. * @returns {string} 执行指令
  127. */
  128. function buildManualInstructions(task, formattedDescription) {
  129. return `
  130. 📋 手动执行模式 - 任务 ${task.task_id}
  131. ## 任务信息
  132. - 任务ID: ${task.task_id}
  133. - 任务名称: ${task.task_name}
  134. ## 任务描述
  135. ${formattedDescription}
  136. ## 执行要求
  137. 1. 仔细阅读任务描述,理解需求
  138. 2. 根据描述开发相应的代码
  139. 3. 确保代码符合项目规范
  140. 4. 完成后,手动调用 update_task_status 工具更新状态
  141. `;
  142. }
  143. /**
  144. * 格式化任务描述
  145. *
  146. * @param {Object} task - 任务对象
  147. * @returns {string} 格式化后的任务描述
  148. */
  149. function formatTaskDescription(task) {
  150. let description = task.task_description || '';
  151. // 确保描述是有效的markdown格式
  152. // 如果描述不是以markdown格式开头,添加一些基本格式
  153. if (!description.trim().startsWith('#')) {
  154. description = `# ${task.task_name}\n\n${description}`;
  155. }
  156. return description;
  157. }
  158. /**
  159. * 验证任务描述格式
  160. *
  161. * @param {string} description - 任务描述
  162. * @returns {boolean} 是否为有效的markdown格式
  163. */
  164. export function validateTaskDescription(description) {
  165. if (!description || typeof description !== 'string') {
  166. return false;
  167. }
  168. // 基本验证:检查是否包含一些内容
  169. if (description.trim().length === 0) {
  170. return false;
  171. }
  172. return true;
  173. }
  174. /**
  175. * 提取任务中的关键信息
  176. *
  177. * @param {Object} task - 任务对象
  178. * @returns {Object} 提取的关键信息
  179. */
  180. export function extractTaskInfo(task) {
  181. const description = task.task_description || '';
  182. // 尝试提取代码文件名和路径(如果任务描述中包含)
  183. const codeNameMatch = description.match(/代码文件名[::]\s*([^\n]+)/i);
  184. const codePathMatch = description.match(/代码路径[::]\s*([^\n]+)/i);
  185. return {
  186. code_name: codeNameMatch ? codeNameMatch[1].trim() : null,
  187. code_path: codePathMatch ? codePathMatch[1].trim() : null,
  188. };
  189. }