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,12 +921,15 @@ router.post('/task/dispatch', async (req, res) => {
921 const taskId = `T-${Date.now().toString(36)}`; 921 const taskId = `T-${Date.now().toString(36)}`;
922 const now = new Date().toISOString().slice(0, 16).replace('T', ' '); 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 // 1. 写入目标 Agent 的 todo.md 927 // 1. 写入目标 Agent 的 todo.md
925 const todoPath = path.join(targetDir, 'todo.md'); 928 const todoPath = path.join(targetDir, 'todo.md');
926 let todoContent = fs.existsSync(todoPath) ? fs.readFileSync(todoPath, 'utf-8') : ''; 929 let todoContent = fs.existsSync(todoPath) ? fs.readFileSync(todoPath, 'utf-8') : '';
927 // 移除空占位行 930 // 移除空占位行
928 todoContent = todoContent.replace(/\| *\| *(暂无待办).*\n?/g, ''); 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 todoContent = todoContent.trimEnd() + '\n' + newTodoRow; 933 todoContent = todoContent.trimEnd() + '\n' + newTodoRow;
931 fs.writeFileSync(todoPath, todoContent, 'utf-8'); 934 fs.writeFileSync(todoPath, todoContent, 'utf-8');
932 935
@@ -935,7 +938,7 @@ router.post(&#39;/task/dispatch&#39;, async (req, res) =&gt; { @@ -935,7 +938,7 @@ router.post(&#39;/task/dispatch&#39;, async (req, res) =&gt; {
935 const planPath = path.join(senderDir, 'plan.md'); 938 const planPath = path.join(senderDir, 'plan.md');
936 let planContent = fs.existsSync(planPath) ? fs.readFileSync(planPath, 'utf-8') : ''; 939 let planContent = fs.existsSync(planPath) ? fs.readFileSync(planPath, 'utf-8') : '';
937 planContent = planContent.replace(/\| *\| *(暂无计划).*\n?/g, ''); 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 planContent = planContent.trimEnd() + '\n' + newPlanRow; 942 planContent = planContent.trimEnd() + '\n' + newPlanRow;
940 fs.writeFileSync(planPath, planContent, 'utf-8'); 943 fs.writeFileSync(planPath, planContent, 'utf-8');
941 } 944 }
@@ -1028,6 +1031,7 @@ router.post(&#39;/task/report&#39;, (req, res) =&gt; { @@ -1028,6 +1031,7 @@ router.post(&#39;/task/report&#39;, (req, res) =&gt; {
1028 1031
1029 const now = new Date().toISOString().slice(0, 16).replace('T', ' '); 1032 const now = new Date().toISOString().slice(0, 16).replace('T', ' ');
1030 const statusEmoji = status === 'done' ? '✅ 完成' : status === 'failed' ? '❌ 失败' : '⏸ 阻塞'; 1033 const statusEmoji = status === 'done' ? '✅ 完成' : status === 'failed' ? '❌ 失败' : '⏸ 阻塞';
  1034 + const safeSummary = (summary || '').replace(/\n/g, '<br>').replace(/\|/g, '&#124;');
1031 1035
1032 // 1. 更新执行者的 todo.md (标记完成) 1036 // 1. 更新执行者的 todo.md (标记完成)
1033 const executorDir = path.join(DATA_DIR, from); 1037 const executorDir = path.join(DATA_DIR, from);
@@ -1063,8 +1067,8 @@ router.post(&#39;/task/report&#39;, (req, res) =&gt; { @@ -1063,8 +1067,8 @@ router.post(&#39;/task/report&#39;, (req, res) =&gt; {
1063 // cells: ['', '#', '子任务', '责任人', '状态', '上次检查', '备注', ''] 1067 // cells: ['', '#', '子任务', '责任人', '状态', '上次检查', '备注', '']
1064 cells[4] = ` ${statusEmoji} `; 1068 cells[4] = ` ${statusEmoji} `;
1065 cells[5] = ` ${now} `; 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 lines[i] = cells.join(' | ').replace(/\*\*/g, ''); // 去掉粗体 1073 lines[i] = cells.join(' | ').replace(/\*\*/g, ''); // 去掉粗体
1070 updated = true; 1074 updated = true;