From 65db2dddc316c0688e8d3b029b63583f42056153 Mon Sep 17 00:00:00 2001 From: ymq Date: Mon, 31 Aug 2026 16:15:00 +0800 Subject: [PATCH] =?UTF-8?q?review=E4=BF=AE=E5=A4=8D=EF=BC=9A=E5=A4=8D?= =?UTF-8?q?=E7=9B=98=E8=AE=A4=E9=A2=86=E6=A0=A1=E9=AA=8C=E8=A1=A5claimed?= =?UTF-8?q?=5Fby=E6=AF=94=E5=AF=B9=E3=80=81LLM=E7=A1=AC=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E5=85=9C=E5=BA=95=E3=80=81=E6=8A=A5=E5=91=8A=E8=90=BD=E7=9B=98?= =?UTF-8?q?=E4=BB=A5write=5Ffile=E5=AE=8C=E6=95=B4=E7=89=88=E4=B8=BA?= =?UTF-8?q?=E5=87=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pipeline_service/agent_loop.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/pipeline_service/agent_loop.py b/pipeline_service/agent_loop.py index 90a6af3..5c1ff13 100644 --- a/pipeline_service/agent_loop.py +++ b/pipeline_service/agent_loop.py @@ -3263,9 +3263,9 @@ async def retrospective_run(project_id, agent_id=None, model_name=None): "UPDATE pipeline_tasks SET state='running', claimed_by=${cb}$, updated_at=NOW() " "WHERE id=${tid}$ AND state='submitted' AND (claimed_by IS NULL OR claimed_by='')", {"cb": claim_token, "tid": task_id}) - chk = await sor.sqlExe("SELECT state FROM pipeline_tasks WHERE id=${tid}$", {"tid": task_id}) + chk = await sor.sqlExe("SELECT state, claimed_by FROM pipeline_tasks WHERE id=${tid}$", {"tid": task_id}) await sor.sqlExe("COMMIT", {}) - if not chk or getattr(chk[0], 'state', '') != 'running': + if not chk or getattr(chk[0], 'state', '') != 'running' or getattr(chk[0], 'claimed_by', '') != claim_token: return {"status": "idle", "message": "复盘任务认领竞争失败"} space_dir = await _get_space_dir(sor, project_id) @@ -3304,7 +3304,9 @@ async def retrospective_run(project_id, agent_id=None, model_name=None): msgs.append({"role": "user", "content": "已执行足够轮次。现在必须立即收尾:write_file 写复盘报告(若未写),然后输出 deliver 提交,禁止再调其它工具。"}) try: - raw = await llm_call_msgs(msgs, model=model_name, temperature=0.3, org_id=org_id) + raw = await asyncio.wait_for( + llm_call_msgs(msgs, model=model_name, temperature=0.3, org_id=org_id), + timeout=_LLM_HARD_TIMEOUT) except Exception as e: err_msg = f"{type(e).__name__}: {str(e)[:400]}" from .task_capability import mark_failed @@ -3337,12 +3339,21 @@ async def retrospective_run(project_id, agent_id=None, model_name=None): return {"status": "failed", "task_id": task_id, "error": "轮次耗尽未交付"} # 复盘报告落盘:规范路径 + deliverables/pm/ + # 报告优先取 LLM write_file 已写的完整版(工具轮写盘),deliver 摘要仅作兜底—— + # 否则完整报告被摘要覆盖、五段结构丢失。 result_text = deliverable.get("result") or deliverable.get("summary") or "" report_rel = os.path.join('projects', project_name or '', 'docs', '02-retrospective', 'retrospective.md') + report_abs = os.path.join(space_dir, report_rel) try: - os.makedirs(os.path.dirname(os.path.join(space_dir, report_rel)), exist_ok=True) - with open(os.path.join(space_dir, report_rel), 'w', encoding='utf-8') as f: - f.write(result_text or '') + if os.path.isfile(report_abs): + with open(report_abs, encoding='utf-8') as f: + on_disk = f.read() + if len(on_disk.strip()) >= len(result_text.strip()): + result_text = on_disk # write_file 版更完整,以盘上为准 + else: + os.makedirs(os.path.dirname(report_abs), exist_ok=True) + with open(report_abs, 'w', encoding='utf-8') as f: + f.write(result_text or '') except Exception as e: logger.warning(f"retrospective report write failed: {e}") from appPublic.uniqueID import getID as _gid @@ -3351,7 +3362,7 @@ async def retrospective_run(project_id, agent_id=None, model_name=None): "id": did, "project_id": project_id, "task_id": task_id, "deliverable_type": "retrospective", "title": "项目复盘报告", "content": result_text[:60000], - "file_path": os.path.join(project_dir, 'deliverables', 'pm', f"{task_id}_retrospective.md"), + "file_path": report_abs, "quality_score": 100, "review_status": "approved", "created_by": agent_id or "pm", }) await sor.sqlExe("COMMIT", {})