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

@@ -28,6 +28,19 @@ def test_agent_service_excludes_runtime_routes(tmp_path):
assert "/api/runtime/gateway/port" not in paths
def test_agent_service_status_includes_scope_metadata(tmp_path):
app = create_app(project_root=tmp_path)
with TestClient(app) as client:
response = client.get("/api/status")
assert response.status_code == 200
payload = response.json()
assert payload["scope"]["design_time_registry"]["root"] == str(tmp_path / "workspaces")
assert payload["scope"]["runtime_assets"]["root"] == str(tmp_path / "runs")
assert "runs/<run_id>" in payload["scope"]["agent_route_note"]
def test_agent_service_read_routes(monkeypatch, tmp_path):
class _FakeSkillsManager:
project_root = tmp_path
@@ -96,9 +109,14 @@ def test_agent_service_read_routes(monkeypatch, tmp_path):
assert profile.status_code == 200
assert profile.json()["profile"]["model_name"] == "deepseek-v3.2"
assert profile.json()["scope_type"] == "runtime_run"
assert skills.status_code == 200
assert skills.json()["skills"][0]["skill_name"] == "demo_skill"
assert skills.json()["scope_type"] == "runtime_run"
assert detail.status_code == 200
assert detail.json()["skill"]["content"] == "# demo"
assert detail.json()["scope_type"] == "runtime_run"
assert workspace_file.status_code == 200
assert workspace_file.json()["content"] == "demo:portfolio_manager:MEMORY.md"
assert workspace_file.json()["scope_type"] == "runtime_run"
assert "runs/<run_id>" in workspace_file.json()["scope_note"]