auto-sync: 2026-05-29 08:32:34

This commit is contained in:
cfdaily
2026-05-29 08:32:34 +08:00
parent 7b3661e2cf
commit 3920aa4fe1
+126
View File
@@ -535,6 +535,132 @@ Project ID: {project_id}
logger.exception("Failed to spawn pangtong review for %s", parent_task.id)
return False
# ------------------------------------------------------------------
# @mention 通知处理 (v2.9 #01)
# ------------------------------------------------------------------
MENTION_MAX_RETRIES = 5
async def _process_mentions(self, db_path: Path,
project_id: str) -> List[str]:
"""扫描 pending mentions → spawn 被 @ 的 Agent
流程(§3.4):
1. 扫描 mention_queue 中 pending 且 retry_count < 5 的记录
2. 按 mentioned_agent 分组,同一 agent 多条 mention 合并为一次 spawn
3. 尝试 spawn,成功 → notified,失败 → retry_count++
"""
if not self.spawner:
return []
bb = Blackboard(db_path)
mentions = bb.get_pending_mentions(max_retries=self.MENTION_MAX_RETRIES)
if not mentions:
return []
# 按 mentioned_agent 分组
agent_mentions: Dict[str, List[Dict]] = {}
for m in mentions:
aid = m["mentioned_agent"]
agent_mentions.setdefault(aid, []).append(m)
processed: List[str] = []
for agent_id, items in agent_mentions.items():
try:
# 构建 mention 摘要
mention_lines = []
task_ids = set()
for item in items:
mention_lines.append(
f"- [{item.get('comment_author', '?')}] {item.get('comment_body', '')[:200]}"
)
task_ids.add(item["task_id"])
# 取第一个 task 作为 spawn 上下文
tid = items[0]["task_id"]
task = bb.get_task(tid)
if not task:
continue
# 构建 mention prompt
prompt = self._build_mention_prompt(
agent_id, task, mention_lines, project_id)
# spawn
result = await self.spawner.spawn_full_agent(
agent_id=agent_id,
message=prompt,
new_session=True,
task_id=tid,
use_main_session=False,
)
if result is not None:
# 成功 → 标记所有该 agent 的 mentions 为 notified
for item in items:
bb.mark_mention_notified(item["id"])
processed.append(agent_id)
logger.info("Mention spawn success: %s (%d mentions)", agent_id, len(items))
else:
# spawn 失败 → 递增 retry_count
for item in items:
bb.mark_mention_retry(item["id"])
logger.warning("Mention spawn failed: %s, retrying next tick", agent_id)
except Exception as e:
logger.exception("Mention processing error for agent %s", agent_id)
for item in items:
try:
if item.get("retry_count", 0) >= self.MENTION_MAX_RETRIES - 1:
bb.mark_mention_failed(item["id"])
else:
bb.mark_mention_retry(item["id"])
except Exception:
pass
return processed
def _build_mention_prompt(self, agent_id: str, task: Any,
mention_lines: List[str],
project_id: str) -> str:
"""构建 @mention 通知 prompt"""
mentions_text = "\n".join(mention_lines[:10])
api_host = getattr(self.spawner, 'api_host', '127.0.0.1') if self.spawner else '127.0.0.1'
api_port = getattr(self.spawner, 'api_port', 8083) if self.spawner else 8083
return f"""你在黑板上被 @ 了,请查看并回应。
## 相关讨论
{mentions_text}
## 任务上下文
- 项目: {project_id}
- 任务: {task.title}
- 描述: {task.description or ''}
## 操作
1. 先读黑板了解上下文:
```bash
curl http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task.id}?expand=all
```
2. 在黑板上回应(写 comment):
```bash
curl -X POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task.id}/comments \
-H 'Content-Type: application/json' \
-d '{{"author": "{agent_id}", "body": "你的回应"}}'
```
3. 如果讨论收敛到可执行的任务,可以创建 sub task
4. 完成后标记 done
```bash
curl -X POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task.id}/status \
-H 'Content-Type: application/json' \
-d '{{"status": "done", "agent": "{agent_id}"}}'
```
"""
def _advance_dependencies(self, db_path: Path) -> List[str]:
"""检查 blocked 任务,若所有依赖已完成则推进为 pending