auto-sync: 2026-05-18 19:05:07
This commit is contained in:
+32
-29
@@ -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}"
|
||||
|
||||
|
||||
# ===================================================================
|
||||
|
||||
Reference in New Issue
Block a user