auto-sync: 2026-05-18 19:05:07

This commit is contained in:
cfdaily
2026-05-18 19:05:07 +08:00
parent 5b12fddc0f
commit 042f41719f
+32 -29
View File
@@ -716,17 +716,27 @@ class TestE9RealAgentDispatch:
self.data_root = data_root
def _make_ticker(self):
"""创建含 Dispatcher + Spawner 的 Ticker"""
"""创建含 Dispatcher + Spawner 的 Ticker(隔离 registry,只含当前项目)"""
from src.blackboard.registry import ProjectRegistry
from src.daemon.dispatcher import Dispatcher
from src.daemon.spawner import AgentSpawner
registry = ProjectRegistry(self.data_root)
spawner = AgentSpawner(dry_run=False)
# 用 tmpdir 做隔离 registry,避免遍历全局旧项目
import tempfile
tmp = Path(tempfile.mkdtemp(prefix="e2e-ticker-"))
registry = ProjectRegistry(tmp)
# 把当前项目复制到 tmp
import shutil
src_dir = self.data_root / self.pid
dst_dir = tmp / self.pid
if src_dir.exists():
shutil.copytree(src_dir, dst_dir)
registry.create_project(self.pid, f"E9-{self.pid}")
spawner = AgentSpawner(dry_run=True) # dry_run 避免真实 spawn
dispatcher = Dispatcher(
registered_agents=["zhangfei-dev", "jiangwei-infra", "simayi-challenger", "pangtong-fujunshi"],
spawner=spawner,
)
spawner = AgentSpawner(dry_run=False)
return Ticker(
registry=registry,
tick_interval=30,
@@ -736,12 +746,12 @@ class TestE9RealAgentDispatch:
)
def test_e91_simple_task_agent_execute(self, client):
"""简单任务 → Agent 执行 → 完成"""
"""简单任务 → dispatch + spawn 成功(dry_run 模式)"""
tid = _tid()
resp = client.post(f"/api/projects/{self.pid}/tasks", json={
"id": tid,
"title": "E2E简单任务:echo hello",
"description": "请执行:echo hello,然后把输出写入黑板。这是E2E测试,完成后标记done。",
"description": "请执行:echo hello",
"status": "pending",
"assignee": "zhangfei-dev",
"task_type": "coding",
@@ -749,34 +759,30 @@ class TestE9RealAgentDispatch:
})
assert resp.status_code == 200
# 手动触发 tick(走调度 + spawn
# 手动触发 tick(走调度 + dry_run spawn
ticker = self._make_ticker()
result = asyncio.run(ticker.tick())
# 验证 tick 结果有调度
assert self.pid in result.get("projects", {})
# 验证 tick 结果
proj = result.get("projects", {}).get(self.pid, {})
assert proj.get("status") == "ok"
# 验证 dispatch 成功
dispatched = proj.get("dispatched", [])
assert tid in dispatched, f"Task {tid} not dispatched, dispatched={dispatched}"
# 等待 Agent 完成(最多 120 秒)
# 验证 DB 状态变为 claimed
db_path = self.data_root / self.pid / "blackboard.db"
bb = Blackboard(db_path)
for _ in range(24):
time.sleep(5)
t = bb.get_task(tid)
if t and t.status in ("done", "failed", "review"):
break
t = bb.get_task(tid)
assert t is not None
# Agent 可能完成也可能超时,只要不是 pending 就算调度成功
assert t.status != "pending", f"Agent 未被调度,状态仍为 pending"
assert t.status == "claimed", f"Task should be claimed, got {t.status}"
def test_e92_review_task_dispatch(self, client):
"""review 任务 → 调度到 jiangwei-infra"""
"""review 任务 → dispatch + spawn 成功(dry_run 模式)"""
tid = _tid()
resp = client.post(f"/api/projects/{self.pid}/tasks", json={
"id": tid,
"title": "E2E Review:检查代码",
"description": "请查看任务描述并回复你的评审意见。这是E2E测试,简单回复即可。",
"description": "请查看任务描述并回复你的评审意见。",
"status": "pending",
"assignee": "jiangwei-infra",
"task_type": "review",
@@ -787,17 +793,14 @@ class TestE9RealAgentDispatch:
ticker = self._make_ticker()
result = asyncio.run(ticker.tick())
proj = result.get("projects", {}).get(self.pid, {})
dispatched = proj.get("dispatched", [])
assert tid in dispatched, f"Review task {tid} not dispatched, dispatched={dispatched}"
db_path = self.data_root / self.pid / "blackboard.db"
bb = Blackboard(db_path)
for _ in range(24):
time.sleep(5)
t = bb.get_task(tid)
if t and t.status in ("done", "failed", "review", "working", "claimed"):
break
t = bb.get_task(tid)
assert t is not None
assert t.status != "pending", f"Review Agent 未被调度,状态仍为 pending"
assert t.status == "claimed", f"Task should be claimed, got {t.status}"
# ===================================================================