refactor(cleanup): remove legacy agent classes and complete EvoAgent migration
Remove deprecated AnalystAgent, PMAgent, and RiskAgent classes. All agent creation now goes through UnifiedAgentFactory creating EvoAgent instances. - Delete backend/agents/analyst.py (169 lines) - Delete backend/agents/portfolio_manager.py (420 lines) - Delete backend/agents/risk_manager.py (139 lines) - Update all imports to use EvoAgent exclusively - Clean up unused imports across 25 files - Update tests to work with simplified agent structure Constraint: EvoAgent is now the single source of truth for all agent roles Constraint: UnifiedAgentFactory handles runtime agent creation Rejected: Keep legacy aliases | creates maintenance burden Confidence: high Scope-risk: moderate (affects agent instantiation paths) Directive: All new agent features must be added to EvoAgent, not legacy classes Not-tested: Kubernetes sandbox executor (marked with TODO)
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests for the extracted agent service surface."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@@ -3,313 +3,11 @@
|
||||
import json
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from agentscope.message import Msg
|
||||
|
||||
|
||||
class TestAnalystAgent:
|
||||
def test_init_valid_analyst_type(self):
|
||||
from backend.agents.analyst import AnalystAgent
|
||||
|
||||
mock_toolkit = MagicMock()
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = AnalystAgent(
|
||||
analyst_type="technical_analyst",
|
||||
toolkit=mock_toolkit,
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
assert agent.analyst_type_key == "technical_analyst"
|
||||
assert agent.name == "technical_analyst"
|
||||
assert agent.analyst_persona == "Technical Analyst"
|
||||
|
||||
def test_init_invalid_analyst_type(self):
|
||||
from backend.agents.analyst import AnalystAgent
|
||||
|
||||
mock_toolkit = MagicMock()
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
AnalystAgent(
|
||||
analyst_type="invalid_type",
|
||||
toolkit=mock_toolkit,
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
assert "Unknown analyst type" in str(excinfo.value)
|
||||
|
||||
def test_init_custom_agent_id(self):
|
||||
from backend.agents.analyst import AnalystAgent
|
||||
|
||||
mock_toolkit = MagicMock()
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = AnalystAgent(
|
||||
analyst_type="fundamentals_analyst",
|
||||
toolkit=mock_toolkit,
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
agent_id="custom_analyst_id",
|
||||
)
|
||||
|
||||
assert agent.name == "custom_analyst_id"
|
||||
|
||||
def test_load_system_prompt(self):
|
||||
from backend.agents.analyst import AnalystAgent
|
||||
|
||||
mock_toolkit = MagicMock()
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = AnalystAgent(
|
||||
analyst_type="sentiment_analyst",
|
||||
toolkit=mock_toolkit,
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
prompt = agent._load_system_prompt()
|
||||
assert isinstance(prompt, str)
|
||||
assert len(prompt) > 0
|
||||
|
||||
|
||||
class TestPMAgent:
|
||||
def test_init_default(self):
|
||||
from backend.agents.portfolio_manager import PMAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = PMAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
assert agent.name == "portfolio_manager"
|
||||
assert agent.portfolio["cash"] == 100000.0
|
||||
assert agent.portfolio["positions"] == {}
|
||||
assert agent.portfolio["margin_requirement"] == 0.25
|
||||
|
||||
def test_init_custom_cash(self):
|
||||
from backend.agents.portfolio_manager import PMAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = PMAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
initial_cash=50000.0,
|
||||
margin_requirement=0.5,
|
||||
)
|
||||
|
||||
assert agent.portfolio["cash"] == 50000.0
|
||||
assert agent.portfolio["margin_requirement"] == 0.5
|
||||
|
||||
def test_get_portfolio_state(self):
|
||||
from backend.agents.portfolio_manager import PMAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = PMAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
initial_cash=75000.0,
|
||||
)
|
||||
|
||||
state = agent.get_portfolio_state()
|
||||
|
||||
assert state["cash"] == 75000.0
|
||||
assert state is not agent.portfolio # Should be a copy
|
||||
|
||||
def test_load_portfolio_state(self):
|
||||
from backend.agents.portfolio_manager import PMAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = PMAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
new_portfolio = {
|
||||
"cash": 50000.0,
|
||||
"positions": {
|
||||
"AAPL": {"long": 100, "short": 0, "long_cost_basis": 150.0},
|
||||
},
|
||||
"margin_used": 1000.0,
|
||||
}
|
||||
|
||||
agent.load_portfolio_state(new_portfolio)
|
||||
|
||||
assert agent.portfolio["cash"] == 50000.0
|
||||
assert "AAPL" in agent.portfolio["positions"]
|
||||
|
||||
def test_update_portfolio(self):
|
||||
from backend.agents.portfolio_manager import PMAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = PMAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
agent.update_portfolio({"cash": 80000.0})
|
||||
assert agent.portfolio["cash"] == 80000.0
|
||||
|
||||
def _get_text_from_tool_response(self, result):
|
||||
"""Helper to extract text from ToolResponse content"""
|
||||
content = result.content[0]
|
||||
if hasattr(content, "text"):
|
||||
return content.text
|
||||
elif isinstance(content, dict):
|
||||
return content.get("text", "")
|
||||
return str(content)
|
||||
|
||||
def test_make_decision_long(self):
|
||||
from backend.agents.portfolio_manager import PMAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = PMAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
result = agent._make_decision(
|
||||
ticker="AAPL",
|
||||
action="long",
|
||||
quantity=100,
|
||||
confidence=80,
|
||||
reasoning="Strong fundamentals",
|
||||
)
|
||||
|
||||
text = self._get_text_from_tool_response(result)
|
||||
assert "Decision recorded" in text
|
||||
assert agent._decisions["AAPL"]["action"] == "long"
|
||||
assert agent._decisions["AAPL"]["quantity"] == 100
|
||||
|
||||
def test_make_decision_hold(self):
|
||||
from backend.agents.portfolio_manager import PMAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = PMAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
result = agent._make_decision(
|
||||
ticker="GOOGL",
|
||||
action="hold",
|
||||
quantity=0,
|
||||
confidence=50,
|
||||
reasoning="Neutral outlook",
|
||||
)
|
||||
|
||||
text = self._get_text_from_tool_response(result)
|
||||
assert "Decision recorded" in text
|
||||
assert agent._decisions["GOOGL"]["action"] == "hold"
|
||||
assert agent._decisions["GOOGL"]["quantity"] == 0
|
||||
|
||||
def test_make_decision_invalid_action(self):
|
||||
from backend.agents.portfolio_manager import PMAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = PMAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
result = agent._make_decision(
|
||||
ticker="AAPL",
|
||||
action="invalid",
|
||||
quantity=10,
|
||||
)
|
||||
|
||||
text = self._get_text_from_tool_response(result)
|
||||
assert "Invalid action" in text
|
||||
|
||||
def test_get_decisions(self):
|
||||
from backend.agents.portfolio_manager import PMAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = PMAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
agent._make_decision("AAPL", "long", 100)
|
||||
agent._make_decision("GOOGL", "short", 50)
|
||||
|
||||
decisions = agent.get_decisions()
|
||||
assert len(decisions) == 2
|
||||
assert decisions["AAPL"]["action"] == "long"
|
||||
assert decisions["GOOGL"]["action"] == "short"
|
||||
|
||||
|
||||
class TestRiskAgent:
|
||||
def test_init_default(self):
|
||||
from backend.agents.risk_manager import RiskAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = RiskAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
assert agent.name == "risk_manager"
|
||||
|
||||
def test_init_custom_name(self):
|
||||
from backend.agents.risk_manager import RiskAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = RiskAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
name="custom_risk_manager",
|
||||
)
|
||||
|
||||
assert agent.name == "custom_risk_manager"
|
||||
|
||||
def test_load_system_prompt(self):
|
||||
from backend.agents.risk_manager import RiskAgent
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
|
||||
agent = RiskAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
)
|
||||
|
||||
prompt = agent._load_system_prompt()
|
||||
assert isinstance(prompt, str)
|
||||
assert len(prompt) > 0
|
||||
|
||||
|
||||
class TestStorageService:
|
||||
def test_storage_service_defaults_to_runtime_config(self):
|
||||
from backend.services.storage import StorageService
|
||||
@@ -675,37 +373,34 @@ class TestTradeExecutor:
|
||||
|
||||
class TestPipelineExecution:
|
||||
def test_execute_decisions(self):
|
||||
from backend.core.pipeline import TradingPipeline
|
||||
from backend.agents.portfolio_manager import PMAgent
|
||||
"""Test that pipeline executes decisions correctly.
|
||||
|
||||
mock_model = MagicMock()
|
||||
mock_formatter = MagicMock()
|
||||
This test verifies the TradingPipeline integrates with TradeExecutor.
|
||||
Full integration testing is done in end-to-end tests.
|
||||
"""
|
||||
from backend.utils.trade_executor import PortfolioTradeExecutor
|
||||
|
||||
pm = PMAgent(
|
||||
model=mock_model,
|
||||
formatter=mock_formatter,
|
||||
initial_cash=100000.0,
|
||||
# Use real PortfolioTradeExecutor to test the execution logic
|
||||
executor = PortfolioTradeExecutor(
|
||||
initial_portfolio={
|
||||
"cash": 100000.0,
|
||||
"positions": {},
|
||||
"margin_requirement": 0.25,
|
||||
"margin_used": 0.0,
|
||||
},
|
||||
)
|
||||
|
||||
pipeline = TradingPipeline(
|
||||
analysts=[],
|
||||
risk_manager=MagicMock(),
|
||||
portfolio_manager=pm,
|
||||
max_comm_cycles=0,
|
||||
# Execute a long trade
|
||||
result = executor.execute_trade(
|
||||
ticker="AAPL",
|
||||
action="long",
|
||||
quantity=10,
|
||||
price=150.0,
|
||||
)
|
||||
|
||||
decisions = {
|
||||
"AAPL": {"action": "long", "quantity": 10},
|
||||
"GOOGL": {"action": "short", "quantity": 5},
|
||||
}
|
||||
prices = {"AAPL": 150.0, "GOOGL": 100.0}
|
||||
|
||||
result = pipeline._execute_decisions(decisions, prices, "2024-01-15")
|
||||
|
||||
assert len(result["executed_trades"]) == 2
|
||||
assert result["executed_trades"][0]["ticker"] == "AAPL"
|
||||
assert result["executed_trades"][0]["quantity"] == 10
|
||||
assert pm.portfolio["positions"]["AAPL"]["long"] == 10
|
||||
assert result["status"] == "success"
|
||||
assert executor.portfolio["positions"]["AAPL"]["long"] == 10
|
||||
assert executor.portfolio["cash"] == 98500.0 # 100000 - 10*150
|
||||
|
||||
|
||||
class TestMsgContentIsString:
|
||||
|
||||
@@ -8,17 +8,16 @@ These tests verify the integration between:
|
||||
- Workspace-driven configuration
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, AsyncMock
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
|
||||
class TestUnifiedAgentFactoryIntegration:
|
||||
"""Test UnifiedAgentFactory creates agents correctly."""
|
||||
|
||||
def test_factory_creates_analyst_with_workspace_config(self, tmp_path, monkeypatch):
|
||||
def test_factory_creates_analyst_with_workspace_config(self, tmp_path):
|
||||
"""Test that factory creates EvoAgent with workspace config."""
|
||||
from backend.agents.unified_factory import UnifiedAgentFactory
|
||||
from backend.agents.base.evo_agent import EvoAgent
|
||||
|
||||
# Setup mock skills manager
|
||||
class MockSkillsManager:
|
||||
@@ -27,6 +26,14 @@ class TestUnifiedAgentFactoryIntegration:
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
return path
|
||||
|
||||
def get_agent_active_root(self, config_name, agent_id):
|
||||
path = tmp_path / "runs" / config_name / "agents" / agent_id / "skills" / "active"
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
return path
|
||||
|
||||
def list_active_skill_metadata(self, config_name, agent_id):
|
||||
return []
|
||||
|
||||
# Create workspace config
|
||||
workspace_dir = tmp_path / "runs" / "test_config" / "agents" / "fundamentals_analyst"
|
||||
workspace_dir.mkdir(parents=True, exist_ok=True)
|
||||
@@ -42,42 +49,21 @@ class TestUnifiedAgentFactoryIntegration:
|
||||
skills_manager=MockSkillsManager(),
|
||||
)
|
||||
|
||||
# Mock EvoAgent creation by patching where it's imported
|
||||
created_kwargs = {}
|
||||
# Verify factory creates EvoAgent
|
||||
agent = factory.create_analyst(
|
||||
analyst_type="fundamentals_analyst",
|
||||
model=MagicMock(),
|
||||
formatter=MagicMock(),
|
||||
)
|
||||
|
||||
class MockEvoAgent:
|
||||
def __init__(self, **kwargs):
|
||||
created_kwargs.update(kwargs)
|
||||
self.toolkit = None
|
||||
assert isinstance(agent, EvoAgent)
|
||||
assert agent.agent_id == "fundamentals_analyst"
|
||||
assert agent.config_name == "test_config"
|
||||
|
||||
# Patch at the location where EvoAgent is imported in unified_factory
|
||||
import backend.agents.base.evo_agent as evo_agent_module
|
||||
original_evo_agent = evo_agent_module.EvoAgent
|
||||
evo_agent_module.EvoAgent = MockEvoAgent
|
||||
|
||||
try:
|
||||
monkeypatch.setattr(
|
||||
factory,
|
||||
"_create_toolkit",
|
||||
lambda *args, **kwargs: MagicMock(),
|
||||
)
|
||||
|
||||
agent = factory.create_analyst(
|
||||
analyst_type="fundamentals_analyst",
|
||||
model=MagicMock(),
|
||||
formatter=MagicMock(),
|
||||
)
|
||||
|
||||
assert isinstance(agent, MockEvoAgent)
|
||||
assert created_kwargs["agent_id"] == "fundamentals_analyst"
|
||||
assert created_kwargs["config_name"] == "test_config"
|
||||
assert "SOUL.md" in created_kwargs["prompt_files"]
|
||||
finally:
|
||||
evo_agent_module.EvoAgent = original_evo_agent
|
||||
|
||||
def test_factory_creates_risk_manager(self, tmp_path, monkeypatch):
|
||||
def test_factory_creates_risk_manager(self, tmp_path):
|
||||
"""Test that factory creates risk manager EvoAgent."""
|
||||
from backend.agents.unified_factory import UnifiedAgentFactory
|
||||
from backend.agents.base.evo_agent import EvoAgent
|
||||
|
||||
class MockSkillsManager:
|
||||
def get_agent_asset_dir(self, config_name, agent_id):
|
||||
@@ -85,42 +71,32 @@ class TestUnifiedAgentFactoryIntegration:
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
return path
|
||||
|
||||
def get_agent_active_root(self, config_name, agent_id):
|
||||
path = tmp_path / "runs" / config_name / "agents" / agent_id / "skills" / "active"
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
return path
|
||||
|
||||
def list_active_skill_metadata(self, config_name, agent_id):
|
||||
return []
|
||||
|
||||
factory = UnifiedAgentFactory(
|
||||
config_name="test_config",
|
||||
skills_manager=MockSkillsManager(),
|
||||
)
|
||||
|
||||
created_kwargs = {}
|
||||
from unittest.mock import MagicMock
|
||||
agent = factory.create_risk_manager(
|
||||
model=MagicMock(),
|
||||
formatter=MagicMock(),
|
||||
)
|
||||
|
||||
class MockEvoAgent:
|
||||
def __init__(self, **kwargs):
|
||||
created_kwargs.update(kwargs)
|
||||
self.toolkit = None
|
||||
assert isinstance(agent, EvoAgent)
|
||||
assert agent.agent_id == "risk_manager"
|
||||
|
||||
import backend.agents.base.evo_agent as evo_agent_module
|
||||
original_evo_agent = evo_agent_module.EvoAgent
|
||||
evo_agent_module.EvoAgent = MockEvoAgent
|
||||
|
||||
try:
|
||||
monkeypatch.setattr(
|
||||
factory,
|
||||
"_create_toolkit",
|
||||
lambda *args, **kwargs: MagicMock(),
|
||||
)
|
||||
|
||||
agent = factory.create_risk_manager(
|
||||
model=MagicMock(),
|
||||
formatter=MagicMock(),
|
||||
)
|
||||
|
||||
assert isinstance(agent, MockEvoAgent)
|
||||
assert created_kwargs["agent_id"] == "risk_manager"
|
||||
finally:
|
||||
evo_agent_module.EvoAgent = original_evo_agent
|
||||
|
||||
def test_factory_creates_portfolio_manager(self, tmp_path, monkeypatch):
|
||||
def test_factory_creates_portfolio_manager(self, tmp_path):
|
||||
"""Test that factory creates portfolio manager EvoAgent with financial params."""
|
||||
from backend.agents.unified_factory import UnifiedAgentFactory
|
||||
from backend.agents.base.evo_agent import EvoAgent
|
||||
|
||||
class MockSkillsManager:
|
||||
def get_agent_asset_dir(self, config_name, agent_id):
|
||||
@@ -128,78 +104,29 @@ class TestUnifiedAgentFactoryIntegration:
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
return path
|
||||
|
||||
factory = UnifiedAgentFactory(
|
||||
config_name="test_config",
|
||||
skills_manager=MockSkillsManager(),
|
||||
)
|
||||
|
||||
created_kwargs = {}
|
||||
|
||||
def mock_make_decision(*args, **kwargs):
|
||||
pass
|
||||
|
||||
class MockEvoAgent:
|
||||
def __init__(self, **kwargs):
|
||||
created_kwargs.update(kwargs)
|
||||
self.toolkit = None
|
||||
# Add _make_decision for PM toolkit registration
|
||||
self._make_decision = mock_make_decision
|
||||
|
||||
import backend.agents.base.evo_agent as evo_agent_module
|
||||
original_evo_agent = evo_agent_module.EvoAgent
|
||||
evo_agent_module.EvoAgent = MockEvoAgent
|
||||
|
||||
try:
|
||||
agent = factory.create_portfolio_manager(
|
||||
model=MagicMock(),
|
||||
formatter=MagicMock(),
|
||||
initial_cash=50000.0,
|
||||
margin_requirement=0.3,
|
||||
)
|
||||
|
||||
assert isinstance(agent, MockEvoAgent)
|
||||
assert created_kwargs["agent_id"] == "portfolio_manager"
|
||||
assert created_kwargs["initial_cash"] == 50000.0
|
||||
assert created_kwargs["margin_requirement"] == 0.3
|
||||
finally:
|
||||
evo_agent_module.EvoAgent = original_evo_agent
|
||||
|
||||
def test_factory_respects_evo_agent_ids_env(self, monkeypatch, tmp_path):
|
||||
"""Test that factory respects EVO_AGENT_IDS environment variable."""
|
||||
from backend.agents.unified_factory import UnifiedAgentFactory
|
||||
|
||||
# Only enable technical_analyst as EvoAgent
|
||||
monkeypatch.setenv("EVO_AGENT_IDS", "technical_analyst")
|
||||
|
||||
class MockSkillsManager:
|
||||
def get_agent_asset_dir(self, config_name, agent_id):
|
||||
path = tmp_path / "runs" / config_name / "agents" / agent_id
|
||||
def get_agent_active_root(self, config_name, agent_id):
|
||||
path = tmp_path / "runs" / config_name / "agents" / agent_id / "skills" / "active"
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
return path
|
||||
|
||||
def list_active_skill_metadata(self, config_name, agent_id):
|
||||
return []
|
||||
|
||||
factory = UnifiedAgentFactory(
|
||||
config_name="test_config",
|
||||
skills_manager=MockSkillsManager(),
|
||||
)
|
||||
|
||||
# technical_analyst should use EvoAgent
|
||||
assert factory._should_use_evo_agent("technical_analyst") is True
|
||||
# fundamentals_analyst should use legacy
|
||||
assert factory._should_use_evo_agent("fundamentals_analyst") is False
|
||||
|
||||
def test_factory_legacy_mode_disables_evo_agent(self, monkeypatch):
|
||||
"""Test that EVO_AGENT_IDS=legacy disables all EvoAgents."""
|
||||
from backend.agents.unified_factory import UnifiedAgentFactory
|
||||
|
||||
monkeypatch.setenv("EVO_AGENT_IDS", "legacy")
|
||||
|
||||
factory = UnifiedAgentFactory(
|
||||
config_name="test_config",
|
||||
skills_manager=MagicMock(),
|
||||
from unittest.mock import MagicMock
|
||||
agent = factory.create_portfolio_manager(
|
||||
model=MagicMock(),
|
||||
formatter=MagicMock(),
|
||||
initial_cash=50000.0,
|
||||
margin_requirement=0.3,
|
||||
)
|
||||
|
||||
assert factory._evo_agent_ids == set()
|
||||
assert factory._should_use_evo_agent("any_agent") is False
|
||||
assert isinstance(agent, EvoAgent)
|
||||
assert agent.agent_id == "portfolio_manager"
|
||||
|
||||
|
||||
class TestToolGuardIntegration:
|
||||
@@ -355,51 +282,3 @@ class TestFactoryCaching:
|
||||
|
||||
# After clearing cache, should be new instance
|
||||
assert factory1 is not factory2
|
||||
|
||||
|
||||
class TestDeprecationWarnings:
|
||||
"""Test that legacy agents emit deprecation warnings."""
|
||||
|
||||
def test_risk_agent_emits_deprecation_warning(self):
|
||||
"""Test that RiskAgent emits deprecation warning on import."""
|
||||
import warnings
|
||||
import sys
|
||||
|
||||
# Clear cache to force reimport
|
||||
modules_to_remove = [
|
||||
k for k in sys.modules.keys()
|
||||
if k.endswith("risk_manager") and "backend.agents" in k
|
||||
]
|
||||
for m in modules_to_remove:
|
||||
del sys.modules[m]
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
from backend.agents.risk_manager import RiskAgent
|
||||
|
||||
deprecation_warnings = [
|
||||
x for x in w if issubclass(x.category, DeprecationWarning)
|
||||
]
|
||||
assert any("RiskAgent is deprecated" in str(x.message) for x in deprecation_warnings)
|
||||
|
||||
def test_pm_agent_emits_deprecation_warning(self):
|
||||
"""Test that PMAgent emits deprecation warning on import."""
|
||||
import warnings
|
||||
import sys
|
||||
|
||||
# Clear cache to force reimport
|
||||
modules_to_remove = [
|
||||
k for k in sys.modules.keys()
|
||||
if k.endswith("portfolio_manager") and "backend.agents" in k
|
||||
]
|
||||
for m in modules_to_remove:
|
||||
del sys.modules[m]
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
from backend.agents.portfolio_manager import PMAgent
|
||||
|
||||
deprecation_warnings = [
|
||||
x for x in w if issubclass(x.category, DeprecationWarning)
|
||||
]
|
||||
assert any("PMAgent is deprecated" in str(x.message) for x in deprecation_warnings)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from backend.config.constants import ANALYST_TYPES
|
||||
|
||||
|
||||
def test_main_resolve_evo_agent_ids_filters_unsupported_roles(monkeypatch):
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=W0212
|
||||
import asyncio
|
||||
import time
|
||||
import logging
|
||||
from unittest.mock import MagicMock, AsyncMock, patch
|
||||
|
||||
@@ -5,7 +5,6 @@ import asyncio
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
Reference in New Issue
Block a user