Commit 2604f5ce40077e2e1affb2f0a35f31332def9b8d

Authored by Yi Bo
1 parent 2e6f62a5

fix(agent-chat): sanitize task description to prevent breaking markdown tables in todo.md/plan.md

Showing 1 changed file with 8 additions and 4 deletions
server/routes/agent-chat.js
... ... @@ -921,12 +921,15 @@ router.post('/task/dispatch', async (req, res) => {
921 921 const taskId = `T-${Date.now().toString(36)}`;
922 922 const now = new Date().toISOString().slice(0, 16).replace('T', ' ');
923 923  
  924 + // 净化多行文本和竖线,防止破坏 Markdown 表格格式
  925 + const safeTask = task.replace(/\n/g, '<br>').replace(/\|/g, '&#124;');
  926 +
924 927 // 1. 写入目标 Agent 的 todo.md
925 928 const todoPath = path.join(targetDir, 'todo.md');
926 929 let todoContent = fs.existsSync(todoPath) ? fs.readFileSync(todoPath, 'utf-8') : '';
927 930 // 移除空占位行
928 931 todoContent = todoContent.replace(/\| *\| *(暂无待办).*\n?/g, '');
929   - const newTodoRow = `| ${taskId} | ${task} | ⬚ 未开始 | ${from} | ${priority} | ${now} | - |\n`;
  932 + const newTodoRow = `| ${taskId} | ${safeTask} | ⬚ 未开始 | ${from} | ${priority} | ${now} | - |\n`;
930 933 todoContent = todoContent.trimEnd() + '\n' + newTodoRow;
931 934 fs.writeFileSync(todoPath, todoContent, 'utf-8');
932 935  
... ... @@ -935,7 +938,7 @@ router.post(&#39;/task/dispatch&#39;, async (req, res) =&gt; {
935 938 const planPath = path.join(senderDir, 'plan.md');
936 939 let planContent = fs.existsSync(planPath) ? fs.readFileSync(planPath, 'utf-8') : '';
937 940 planContent = planContent.replace(/\| *\| *(暂无计划).*\n?/g, '');
938   - const newPlanRow = `| ${planId} | ${task} | ${to} | 🔄 已分发 | ${now} | taskId: ${taskId} |\n`;
  941 + const newPlanRow = `| ${planId} | ${safeTask} | ${to} | 🔄 已分发 | ${now} | taskId: ${taskId} |\n`;
939 942 planContent = planContent.trimEnd() + '\n' + newPlanRow;
940 943 fs.writeFileSync(planPath, planContent, 'utf-8');
941 944 }
... ... @@ -1028,6 +1031,7 @@ router.post(&#39;/task/report&#39;, (req, res) =&gt; {
1028 1031  
1029 1032 const now = new Date().toISOString().slice(0, 16).replace('T', ' ');
1030 1033 const statusEmoji = status === 'done' ? '✅ 完成' : status === 'failed' ? '❌ 失败' : '⏸ 阻塞';
  1034 + const safeSummary = (summary || '').replace(/\n/g, '<br>').replace(/\|/g, '&#124;');
1031 1035  
1032 1036 // 1. 更新执行者的 todo.md (标记完成)
1033 1037 const executorDir = path.join(DATA_DIR, from);
... ... @@ -1063,8 +1067,8 @@ router.post(&#39;/task/report&#39;, (req, res) =&gt; {
1063 1067 // cells: ['', '#', '子任务', '责任人', '状态', '上次检查', '备注', '']
1064 1068 cells[4] = ` ${statusEmoji} `;
1065 1069 cells[5] = ` ${now} `;
1066   - if (summary && cells.length >= 7) {
1067   - cells[6] = ` ${summary} `;
  1070 + if (safeSummary && cells.length >= 7) {
  1071 + cells[6] = ` ${safeSummary} `;
1068 1072 }
1069 1073 lines[i] = cells.join(' | ').replace(/\*\*/g, ''); // 去掉粗体
1070 1074 updated = true;
... ...