auto-sync: 2026-05-21 13:17:49

This commit is contained in:
cfdaily
2026-05-21 13:17:49 +08:00
parent e12aba10e6
commit a503938d26
+129 -4
View File
@@ -241,7 +241,132 @@ def _build_claim_prompt(self, agent_id, tasks, project_id):
---
## 5. 场景对比
## 5. 广播认领完整生命周期
> 本节记录从任务创建到最终闭环的完整链路,包括所有已实现但此前未在设计文档中记录的机制。
### 5.1 完整流程图
```
用户创建任务 → pending
Ticker 检测到 pending 任务
有确定性路径?(retry/handoff/assignee/生命周期)
├─ 是 → 直接 spawn 指定 Agent
└─ 否 → 进入广播认领
广播前检查全局并发(counter.is_near_limit()
→ 接近上限?跳过本轮
获取空闲 Agent 列表(从 config agents 列表取)
→ 无空闲?log warning,不递增 retry_count,等下轮
spawn 所有空闲 Agent,传入 claim prompt
retry_count++(本轮广播计数)
┌─ 有人 claim → 正常执行流程
└─ 无人 claim
claimed 超时(5min)→ _check_timeouts 重置为 pending
retry_count 已递增
retry_count < 3?→ 下轮 Ticker 继续广播
retry_count >= 3?→ escalate to 庞统
```
### 5.2 retry_count 的三种递增场景
| 场景 | 触发位置 | retry_count++ | 说明 |
|------|----------|-----------------|------|
| 广播后无人认领 | `_broadcast_claim` L536 | ✅ 是 | 每轮广播递增,记录广播轮次 |
| claimed 超时回收 | `_check_timeouts` L724 | ✅ 是 | Agent 认领后未执行,视为失败 |
| 无空闲 Agent | `_broadcast_claim` L527 | ❌ 否 | 系统容量问题,不是任务问题 |
### 5.3 超时阈值(与 working 状态一致)
| 状态 | 超时 | 处理 |
|------|------|------|
| claimed | `claim_timeout_minutes = 5.0` | → pendingretry_count < 3)或 escalatedretry_count >= 3 |
| working | `default_task_timeout_minutes = 30.0` | → failed |
超时后 retry_count >= 3 时的处理与 working 超时一致:标记 escalated,触发用户介入流程。
### 5.4 庞统兜底(delegate 模式)
当任务进入以下状态时,Router 路由到 `FALLBACK_AGENT = "pangtong-fujunshi"`mode="delegate"
- 广播 3 轮无人认领(retry_count >= 3
- 确定性路由无法匹配(模糊场景)
庞统收到的 delegate prompt 包含:任务信息 + 团队能力列表 + API 端点。庞统可以:
1. 直接分配给指定 Agent(通过 claim API
2. 自己执行
3. 判断任务不合理 → cancel
### 5.5 用户介入链路(已完整实现)
当任务 escalated 后,用户介入的完整链路:
```
Agent 超时/广播无人认领
→ Ticker 标记 status="escalated"
→ SSE broker.publish_sync("task_updated", {...})
→ 前端 EventSource 实时收到事件
→ 通知中心推送 "{old_status} → escalated"
→ 卡片红色高亮 + ⚠️ 图标
→ 用户点开 TaskModal
→ 看到 escalated 按钮:
· ▶ 继续执行 (→ working)
· 🔄 重新分配 (→ pending, retry_count 重置)
· 🚫 取消 (→ cancelled)
▸ 高级操作:
· (可扩展更多手动干预)
→ 用户点击 → POST /tasks/{id}/status → SSE 推送 → 状态更新
```
**已实现代码对应表:**
| 环节 | 代码文件 | 具体实现 |
|------|----------|----------|
| 标记 escalated | `ticker.py` _check_timeouts / _broadcast_claim | _transition_status(conn, task_id, "escalated", ...) |
| SSE 推送 | `blackboard_routes.py` update_status | broker.publish_sync("task_updated", ...) |
| SSE 基础设施 | `sse.py` / `sse_routes.py` | SSEBroker + EventSource endpoint |
| 前端 SSE 监听 | `store.ts` startSSE() | addEventListener('task_updated', ...) |
| 前端通知中心 | `store.ts` _pushSseEvent() | 通知列表 + 未读计数 |
| escalated 按钮 | `TaskModal.tsx` PRIMARY_ACTIONS[escalated] | ▶ 继续执行 + 🔄 重新分配 |
| escalated 高级操作 | `TaskModal.tsx` ADVANCED_ACTIONS | 🚫 取消 |
| 状态转换 API | `blackboard_routes.py` POST /tasks/{id}/status | VALID_TRANSITIONS 校验 |
| 转换矩阵 | `db.py` VALID_TRANSITIONS | escalated → {working, pending, cancelled} |
### 5.6 前端按钮完整矩阵
**PRIMARY_ACTIONS(主操作区,直接展示):**
| 状态 | 按钮 | 目标状态 | 说明 |
|------|------|----------|------|
| pending | ⏳ 等待 Agent 自动认领... | — | 提示文字(待补取消按钮) |
| claimed | ⏳ Agent 已认领,即将开始... | — | 提示文字 |
| working | ⏸ 暂停任务 | paused | |
| review | 🔍 Agent 审查中... | — | 提示文字 |
| waiting_human | ✅ 确认完成 / 🔄 拒绝继续做 | done / working | |
| escalated | ▶ 继续执行 / 🔄 重新分配 | working / pending | |
| failed | 🔄 重试 | pending | |
| blocked | 🔓 解除阻塞 | pending | |
| paused | ▶ 继续执行 / 🚫 取消任务 | working / cancelled | |
| done | 📦 归档 | — | |
| cancelled | 📦 归档 | — | |
**ADVANCED_ACTIONS(折叠在"▸ 高级操作"下):**
| 状态 | 按钮 | 说明 |
|------|------|------|
| working | 🔍 手动提交审查 / 🚫 取消 | |
| review | ✅ 手动通过 / 🔄 打回重做 | |
| failed | 🚫 取消 | |
---
## 6. 场景对比
| 场景 | 改前(独立 LLM 分配) | 改后(广播认领 + 确定性交接) |
|------|---------------------|---------------------------|
@@ -254,7 +379,7 @@ def _build_claim_prompt(self, agent_id, tasks, project_id):
---
## 6. 代码量
## 7. 代码量
- **删**~130 行(`LLMDriver` + routing config 初始化 + config.yaml routing 节)
- **改**~30 行(`Router.route()` 末尾 + `Dispatcher._build_spawn_message()` delegate 分支)
@@ -263,7 +388,7 @@ def _build_claim_prompt(self, agent_id, tasks, project_id):
---
## 7. 风险与缓解
## 8. 风险与缓解
| # | 风险 | 评估 | 缓解 |
|---|------|------|------|
@@ -275,7 +400,7 @@ def _build_claim_prompt(self, agent_id, tasks, project_id):
---
## 8. 实施步骤
## 9. 实施步骤
1. `router.py`:删除 `LLMDriver` 类 + `AgentRouter` 去掉 `llm_driver` + `route()` 末尾改 delegate
2. `ticker.py`:新增 `_broadcast_claim` + `_build_claim_prompt`,修改 `_dispatch_pending` 增加 广播路径