feat(agent): complete EvoAgent integration for all 6 agent roles

Migrate all agent roles from Legacy to EvoAgent architecture:
- fundamentals_analyst, technical_analyst, sentiment_analyst, valuation_analyst
- risk_manager, portfolio_manager

Key changes:
- EvoAgent now supports Portfolio Manager compatibility methods (_make_decision,
  get_decisions, get_portfolio_state, load_portfolio_state, update_portfolio)
- Add UnifiedAgentFactory for centralized agent creation
- ToolGuard with batch approval API and WebSocket broadcast
- Legacy agents marked deprecated (AnalystAgent, RiskAgent, PMAgent)
- Remove backend/agents/compat.py migration shim
- Add run_id alongside workspace_id for semantic clarity
- Complete integration test coverage (13 tests)
- All smoke tests passing for 6 agent roles

Constraint: Must maintain backward compatibility with existing run configs
Constraint: Memory support must work with EvoAgent (no fallback to Legacy)
Rejected: Separate PM implementation for EvoAgent | unified approach cleaner
Confidence: high
Scope-risk: broad
Directive: EVO_AGENT_IDS env var still respected but defaults to all roles
Not-tested: Kubernetes sandbox mode for skill execution
This commit is contained in:
2026-04-02 00:55:08 +08:00
parent 0fa413380c
commit 16b54d5ccc
73 changed files with 9454 additions and 904 deletions

View File

@@ -19,13 +19,31 @@ agent_factory: AgentFactory | None = None
workspace_manager: WorkspaceManager | None = None
def _build_scope_payload(project_root: Path) -> dict[str, object]:
return {
"design_time_registry": {
"root": str(project_root / "workspaces"),
"meaning": "Persistent control-plane workspace registry",
},
"runtime_assets": {
"root": str(project_root / "runs"),
"meaning": "Run-scoped runtime state and agent assets",
},
"agent_route_note": (
"On `/api/workspaces/{workspace_id}/agents/...`, design-time CRUD "
"routes still use `workspaces/`, while profile/skills/file routes "
"use `workspace_id` as a run id under `runs/<run_id>/`."
),
}
def create_app(project_root: Path | None = None) -> FastAPI:
"""Create the agent control-plane app."""
resolved_project_root = project_root or Path(__file__).resolve().parents[2]
@asynccontextmanager
async def lifespan(_app: FastAPI) -> AsyncGenerator[None, None]:
"""Initialize workspace and registry state for the control plane."""
"""Initialize design-time workspace and registry state for the control plane."""
global agent_factory, workspace_manager
workspace_manager = WorkspaceManager(project_root=resolved_project_root)
@@ -34,7 +52,7 @@ def create_app(project_root: Path | None = None) -> FastAPI:
registry = get_registry()
print("✓ 大时代 API started")
print(f" - Workspaces root: {agent_factory.workspaces_root}")
print(f" - Design workspaces root: {agent_factory.workspaces_root}")
print(f" - Registered agents: {registry.get_agent_count()}")
yield
@@ -63,6 +81,7 @@ def create_app(project_root: Path | None = None) -> FastAPI:
if workspace_manager
else 0
),
"scope_roots": _build_scope_payload(resolved_project_root),
}
@app.get("/api/status")
@@ -72,6 +91,7 @@ def create_app(project_root: Path | None = None) -> FastAPI:
return {
"status": "operational",
"registry": registry.get_stats(),
"scope": _build_scope_payload(resolved_project_root),
}
app.include_router(workspaces_router)