From 0f3b4561fad551fca660304745cdc8a912d6f6d8 Mon Sep 17 00:00:00 2001 From: cfdaily Date: Tue, 26 May 2026 08:23:48 +0800 Subject: [PATCH] auto-sync: 2026-05-26 08:23:47 --- src/daemon/dispatcher.py | 46 ++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/src/daemon/dispatcher.py b/src/daemon/dispatcher.py index 1475b56..d464fc4 100644 --- a/src/daemon/dispatcher.py +++ b/src/daemon/dispatcher.py @@ -154,17 +154,8 @@ class Dispatcher: _routing_db = Path(project_config["db_path"]) if project_config and "db_path" in project_config else None agent_id = decision["agent_id"] - # 检查并发限制 - if self.counter and level in (DispatchLevel.FULL_AGENT, DispatchLevel.ESCALATE): - if not await self.counter.can_acquire(agent_id): - self._record_routing(task, decision, "skipped", "Agent busy", _routing_db) - return { - "level": level.value, - "agent_id": agent_id, - "session_id": None, - "status": "skipped", - "reason": "Agent busy (concurrent limit)", - } + # v2.7.2: counter 检查移到 spawn_full_agent 内部 + # dispatcher 不再管 counter acquire/release # 本地执行 if level == DispatchLevel.LOCAL: @@ -190,16 +181,11 @@ class Dispatcher: } try: - if self.counter: - await self.counter.acquire(agent_id) - # [v2.7.1] Mail: spawn 前系统标 working is_mail = project_config.get("project_id") == "_mail" if project_config else False if is_mail: db_path = Path(project_config["db_path"]) if project_config and "db_path" in project_config else None if not db_path or not self._mail_auto_working(task.id, db_path): - if self.counter: - self.counter.release(agent_id) self._record_routing(task, decision, "error", "mail working failed", _routing_db) return {"level": level.value, "agent_id": agent_id, "session_id": None, "status": "error", @@ -209,31 +195,23 @@ class Dispatcher: message = self._build_spawn_message(task, agent_id, project_config, mode=decision.get("mode", "")) - # [v2.7.1] Mail: on_complete 增强自动标 done/failed + # v2.7.2: on_complete 只含业务逻辑,不含 counter.release + # counter.release 由 spawn_full_agent 内部的 wrapped_on_complete 保证 on_complete = None if is_mail: _task_id = task.id - _agent_id = agent_id _mail_db = db_path _must_haves = task.must_haves or "" - _counter = self.counter _dispatcher = self def _mail_on_complete(aid, outcome): - # 先 release counter - if _counter: - _counter.release(aid) - # 自动标 done/failed(幻觉门控) - # 不管 outcome 是什么,都检查是否有回复 + # 幻觉门控:检查是否有回复,自动标 done/failed try: _dispatcher._mail_auto_complete(_task_id, aid, _mail_db, _must_haves) except Exception as e: logger.error("Mail %s: on_complete error: %s", _task_id, e) on_complete = _mail_on_complete - else: - on_complete = ( - lambda aid, _outcome: self.counter.release(aid) - ) if self.counter else None + # Task 不需要业务回调 session_id = await self.spawner.spawn_full_agent( agent_id=agent_id, @@ -255,9 +233,17 @@ class Dispatcher: "status": "dispatched", "reason": decision["reason"], } + except AgentBusyError: + # v2.7.2: agent 被 counter 占用或冷却中 + self._record_routing(task, decision, "skipped", "Agent busy", _routing_db) + return { + "level": level.value, + "agent_id": agent_id, + "session_id": None, + "status": "skipped", + "reason": "Agent busy (concurrent limit or cooling down)", + } except Exception as e: - if self.counter: - self.counter.release(agent_id) self._record_routing(task, decision, "error", str(e), _routing_db) return { "level": level.value,