diff --git a/docs/design/v3.0-router-refactor.md b/docs/design/v3.0-router-refactor.md index d470465..b67d503 100644 --- a/docs/design/v3.0-router-refactor.md +++ b/docs/design/v3.0-router-refactor.md @@ -169,23 +169,61 @@ Ticker._tick_project() ### 4.3 新增 `_broadcast_claim`(ticker.py) -在 `_dispatch_pending` 中,确定性路径都不匹配时,调用新方法广播认领: +司马懿建议:攒一批任务,每轮 ticker 最多广播一次(而非每个 pending 任务触发一次广播)。 +5 个任务只需 spawn 5 个 Agent,而不是 25 个。 + +广播前检查全局并发(司马懿建议 1):接近上限时跳过本轮广播。 ```python -async def _broadcast_claim(self, task, db_path, project_id): - """广播任务给所有空闲 Agent,自主认领""" +async def _broadcast_claim(self, tasks, db_path, project_id): + """广播一批待认领任务给所有空闲 Agent,每轮最多广播一次""" + # 全局并发检查 + if self.counter and self.counter.global_active >= self.counter._max_global - 1: + logger.info("Skipping broadcast: global concurrent near limit") + return [] + idle_agents = self._get_idle_agents() + if not idle_agents: + return [] + + spawned = [] for agent_id in idle_agents: - # 并发检查 if not await self.counter.can_acquire(agent_id): continue - prompt = self._build_claim_prompt(agent_id, task, project_id) - await self.spawner.spawn_full_agent( + prompt = self._build_claim_prompt(agent_id, tasks, project_id) + await self.counter.acquire(agent_id) + session_id = await self.spawner.spawn_full_agent( agent_id=agent_id, message=prompt, - task_id=task.id, on_complete=lambda aid, _: self.counter.release(aid), ) + spawned.append(agent_id) + return spawned +``` + +广播 prompt 包含所有 pending 任务列表: +```python +def _build_claim_prompt(self, agent_id, tasks, project_id): + task_list = "\n".join([ + f"- ID: {t.id}, 标题: {t.title}, 类型: {t.task_type}, 优先级: {t.priority}" + for t in tasks + ]) + return f"""你是 {agent_id}。黑板上有 {len(tasks)} 个待认领任务。 + +## 待认领任务 +{task_list} + +## 操作 +1. 读黑板查看详情: + curl http://{api}/api/projects/{project_id}/tasks?status=pending + +2. 选择适合你的任务并认领: + curl -X POST http://{api}/api/projects/{project_id}/tasks/{task_id}/claim \ + -H 'Content-Type: application/json' -d '{{"agent": "{agent_id}"}}' + +3. 认领成功后开始执行(状态改为 working) +4. 没有适合你的任务则退出 +""" ``` ### 4.4 Dispatcher 增加 delegate 模式(dispatcher.py) @@ -197,9 +235,9 @@ async def _broadcast_claim(self, task, db_path, project_id): ### 4.6 config/default.yaml 去掉 routing 节 -### 4.7 广播轮次追踪 +### 4.7 无人认领检测(复用 retry_count) -`_broadcast_claim` 写入 events 表 `broadcast_sent` 事件,`_check_timeouts` 检测连续广播轮次。 +司马懿建议:不需要新增 broadcast_sent 事件。无人认领重置 pending 时 retry_count 已在递增,直接用它判断阈值。当 `retry_count >= 3` 时 escalate to 庞统。 --- @@ -220,7 +258,7 @@ async def _broadcast_claim(self, task, db_path, project_id): - **删**:~130 行(`LLMDriver` + routing config 初始化 + config.yaml routing 节) - **改**:~30 行(`Router.route()` 末尾 + `Dispatcher._build_spawn_message()` delegate 分支) -- **新增**:~60 行(`_broadcast_claim` + `_build_claim_prompt` + 广播轮次追踪) +- **新增**:~60 行(`_broadcast_claim` + `_build_claim_prompt`) - **净减**:~40 行 ---