from __future__ import annotations import asyncio from types import SimpleNamespace from typing import Any from beaver.coordinator import AgentDescriptor, ExecutionGraph, ExecutionNode from beaver.engine import AgentRunResult from beaver.tasks import TaskExecutionPlan, TaskRecord from beaver.tasks.attempt_orchestrator import TaskAttemptOrchestrator class FakeTaskService: def start_run(self, task_id: str, **_: Any) -> None: return None def append_run(self, task_id: str, run_id: str, **_: Any) -> TaskRecord: return self.task class FakeSessionManager: def __init__(self) -> None: self.events: list[dict[str, Any]] = [] def append_message(self, session_id: str, **kwargs: Any) -> None: self.events.append({"session_id": session_id, **kwargs}) def update_latest_assistant_event_payload(self, *args: Any, **kwargs: Any) -> None: return None def get_run_event_records(self, session_id: str, run_id: str) -> list[Any]: return [] class LegacyTeamPlanner: async def plan(self, **_: Any) -> TaskExecutionPlan: return TaskExecutionPlan( mode="team", reason="legacy plan should be ignored by orchestrator", graph=ExecutionGraph( strategy="sequence", nodes=[ ExecutionNode("collect", "Collect", AgentDescriptor(name="collect")), ], ), ) def _task() -> TaskRecord: return TaskRecord( task_id="task-1", session_id="session-1", description="finance comparison", goal="finance comparison", constraints=[], priority=0, status="open", creator="test", created_at="now", updated_at="now", ) def test_builtin_tools_do_not_export_legacy_agent_team_tool() -> None: import beaver.tools.builtins as builtins assert "AgentTeamTool" not in builtins.__all__ assert not hasattr(builtins, "AgentTeamTool") def test_task_orchestrator_does_not_execute_legacy_planner_team_graph() -> None: task = _task() task_service = FakeTaskService() task_service.task = task session_manager = FakeSessionManager() loaded = SimpleNamespace( task_service=task_service, task_execution_planner=LegacyTeamPlanner(), session_manager=session_manager, run_memory_store=None, ) orchestrator = TaskAttemptOrchestrator( loaded=loaded, create_loop=lambda: None, make_provider_bundle_for_task=lambda *_: None, ) async def fail_if_called(*args: Any, **kwargs: Any) -> Any: raise AssertionError("legacy planner team graph must not start TeamService") async def runner(message: str, **kwargs: Any) -> AgentRunResult: return AgentRunResult( session_id="session-1", run_id="main-run", output_text="single path", finish_reason="stop", tool_iterations=0, ) orchestrator._run_team_for_task = fail_if_called # type: ignore[method-assign] result = asyncio.run( orchestrator.run( message="compare finance", runner=runner, kwargs={ "session_id": "session-1", "provider_bundle": SimpleNamespace(), "include_skill_assembly": False, }, task=task, ) ) assert result.output_text == "single path" synthesis_events = [ event for event in session_manager.events if event.get("event_type") == "task_synthesis_completed" ] assert synthesis_events[0]["event_payload"]["task_outcome"] == "single"