From df2b7186630ccda0b393de6109cf39db1e855cbb Mon Sep 17 00:00:00 2001 From: cfdaily Date: Fri, 29 May 2026 07:55:09 +0800 Subject: [PATCH] auto-sync: 2026-05-29 07:55:09 --- src/daemon/bootstrap.py | 104 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/src/daemon/bootstrap.py b/src/daemon/bootstrap.py index 9e2ab5e..c205dfc 100644 --- a/src/daemon/bootstrap.py +++ b/src/daemon/bootstrap.py @@ -213,3 +213,107 @@ class BootstrapBuilder: project_context=project_context, experiences=experiences, ) + + def build_for_review( + self, + parent_task: Any, + summary: Dict[str, Any], + outputs: List[Dict[str, Any]], + comments: List[Dict[str, Any]], + round_num: int, + max_rounds: int = 5, + project_config: Optional[Dict] = None, + ) -> str: + """从 parent task 构建庞统 review 上下文(便捷方法) + + Args: + parent_task: parent Task 对象 + summary: get_subtasks_summary() 返回的状态摘要 + outputs: get_aggregate_outputs() 返回的产出列表 + comments: get_round_comments() 返回的讨论列表 + round_num: 当前轮次 + max_rounds: 最大轮次 + project_config: 项目配置 + """ + task_context = { + "task_id": parent_task.id, + "title": parent_task.title, + "description": parent_task.description, + "task_type": parent_task.task_type, + "must_haves": parent_task.must_haves, + } + + project_context = None + if project_config: + project_context = { + "name": project_config.get("name"), + "description": project_config.get("description"), + "agents": project_config.get("agents", []), + } + + # 构建基础 bootstrap + bootstrap = self.build( + role="pangtong", + task_context=task_context, + project_context=project_context, + ) + + # 追加 review 专用上下文 + review_section = self._format_review_context( + summary, outputs, comments, round_num, max_rounds) + + return bootstrap + "\n\n---\n\n" + review_section + + def _format_review_context( + self, + summary: Dict[str, Any], + outputs: List[Dict[str, Any]], + comments: List[Dict[str, Any]], + round_num: int, + max_rounds: int, + ) -> str: + """格式化庞统 review 专用上下文""" + parts = ["## 庞统 Review 上下文"] + + # Sub Task 状态摘要 + parts.append(f"### 本轮 Sub Task 状态") + parts.append(f"- 完成: {summary.get('done', 0)}") + parts.append(f"- 失败: {summary.get('failed', 0)}") + parts.append(f"- 取消: {summary.get('cancelled', 0)}") + parts.append(f"- 总计: {summary.get('total', 0)}") + parts.append(f"- 当前轮次: {round_num}/{max_rounds}") + + # 成果物摘要(限制 20 条) + if outputs: + parts.append("\n### 成果物") + for o in outputs[:20]: + parts.append( + f"- [{o.get('task_title', '?')}] " + f"{o.get('title', '?')} ({o.get('output_type', '?')}) " + f"by {o.get('agent', '?')}" + ) + else: + parts.append("\n### 成果物\n无") + + # 讨论摘要(限制 50 条) + if comments: + parts.append("\n### 黑板讨论") + for c in comments[:50]: + body = (c.get('body', '') or '')[:200] + parts.append( + f"[{(c.get('created_at', '') or '?')[:16]}] " + f"{c.get('author', '?')}: {body}" + ) + else: + parts.append("\n### 黑板讨论\n无") + + # 失败处理指引 + failed = summary.get('failed', 0) + if failed > 0: + parts.append( + f"\n### 失败处理\n" + f"有 {failed} 个 sub task failed," + f"优先判断是应该重试(同一 Agent)、换人(换 Agent)、还是调整方案。" + ) + + return "\n".join(parts)