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

@@ -463,6 +463,34 @@ class StateSync:
limit=self.storage.max_feed_history,
) or self._state.get("last_day_history", [])
persisted_state = self.storage.read_persisted_server_state()
dashboard_snapshot = (
self.storage.build_dashboard_snapshot_from_state(self._state)
if include_dashboard
else None
)
dashboard_holdings = (
dashboard_snapshot.get("holdings", [])
if dashboard_snapshot is not None
else self._state.get("holdings", [])
)
dashboard_trades = (
dashboard_snapshot.get("trades", [])
if dashboard_snapshot is not None
else self._state.get("trades", [])
)
dashboard_stats = (
dashboard_snapshot.get("stats", {})
if dashboard_snapshot is not None
else self._state.get("stats", {})
)
dashboard_leaderboard = (
dashboard_snapshot.get("leaderboard", [])
if dashboard_snapshot is not None
else self._state.get("leaderboard", [])
)
portfolio_state = self._state.get("portfolio") or persisted_state.get("portfolio") or {}
payload = {
"server_mode": self._state.get("server_mode", "live"),
"is_backtest": self._state.get("is_backtest", False),
@@ -476,24 +504,23 @@ class StateSync:
"trading_days_completed",
0,
),
"holdings": self._state.get("holdings", []),
"trades": self._state.get("trades", []),
"stats": self._state.get("stats", {}),
"leaderboard": self._state.get("leaderboard", []),
"portfolio": self._state.get("portfolio", {}),
"holdings": dashboard_holdings,
"trades": dashboard_trades,
"stats": dashboard_stats,
"leaderboard": dashboard_leaderboard,
"portfolio": portfolio_state,
"realtime_prices": self._state.get("realtime_prices", {}),
"data_sources": self._state.get("data_sources", {}),
"price_history": self._state.get("price_history", {}),
}
if include_dashboard:
dashboard_snapshot = self.storage.build_dashboard_snapshot_from_state(self._state)
payload["dashboard"] = {
"summary": dashboard_snapshot.get("summary"),
"holdings": dashboard_snapshot.get("holdings"),
"stats": dashboard_snapshot.get("stats"),
"trades": dashboard_snapshot.get("trades"),
"leaderboard": dashboard_snapshot.get("leaderboard"),
"holdings": dashboard_holdings,
"stats": dashboard_stats,
"trades": dashboard_trades,
"leaderboard": dashboard_leaderboard,
}
return payload