Files
evotraders/backend/tests/test_agent_workspace.py
2026-03-30 17:46:44 +08:00

234 lines
7.6 KiB
Python

# -*- coding: utf-8 -*-
from backend.agents.prompt_factory import build_agent_system_prompt
from backend.agents.skills_manager import SkillsManager
from backend.agents.workspace_manager import WorkspaceManager
class _DummyToolkit:
def get_agent_skill_prompt(self):
return ""
def get_activated_notes(self):
return ""
def test_workspace_manager_creates_core_agent_files(tmp_path):
manager = WorkspaceManager(project_root=tmp_path)
manager.initialize_default_assets(
config_name="demo",
agent_ids=["risk_manager"],
analyst_personas={},
)
asset_dir = tmp_path / "runs" / "demo" / "agents" / "risk_manager"
assert (asset_dir / "SOUL.md").exists()
assert (asset_dir / "PROFILE.md").exists()
assert (asset_dir / "AGENTS.md").exists()
assert (asset_dir / "MEMORY.md").exists()
assert (asset_dir / "POLICY.md").exists()
assert (asset_dir / "agent.yaml").exists()
assert (asset_dir / "skills" / "installed").is_dir()
assert (asset_dir / "skills" / "active").is_dir()
assert (asset_dir / "skills" / "disabled").is_dir()
assert (asset_dir / "skills" / "local").is_dir()
def test_workspace_manager_seeds_risk_prompt_content(tmp_path):
manager = WorkspaceManager(project_root=tmp_path)
manager.initialize_default_assets(
config_name="demo",
agent_ids=["risk_manager"],
analyst_personas={},
)
asset_dir = tmp_path / "runs" / "demo" / "agents" / "risk_manager"
soul = (asset_dir / "SOUL.md").read_text(encoding="utf-8")
guide = (asset_dir / "AGENTS.md").read_text(encoding="utf-8")
assert "风险管理经理" in soul
assert "优先使用可用的风险工具量化集中度" in guide
def test_agent_workspace_config_controls_prompt_files(tmp_path, monkeypatch):
manager = WorkspaceManager(project_root=tmp_path)
manager.initialize_default_assets(
config_name="demo",
agent_ids=["risk_manager"],
analyst_personas={},
)
asset_dir = tmp_path / "runs" / "demo" / "agents" / "risk_manager"
(asset_dir / "SOUL.md").write_text("soul-line", encoding="utf-8")
(asset_dir / "PROFILE.md").write_text("profile-line", encoding="utf-8")
(asset_dir / "MEMORY.md").write_text("memory-line", encoding="utf-8")
(asset_dir / "agent.yaml").write_text(
"prompt_files:\n"
" - SOUL.md\n"
" - MEMORY.md\n",
encoding="utf-8",
)
from backend.agents import prompt_factory
monkeypatch.setattr(
prompt_factory,
"SkillsManager",
lambda: SkillsManager(project_root=tmp_path),
)
prompt = build_agent_system_prompt(
agent_id="risk_manager",
config_name="demo",
toolkit=_DummyToolkit(),
)
assert "soul-line" in prompt
assert "memory-line" in prompt
assert "profile-line" not in prompt
def test_prompt_is_built_from_workspace_defaults_without_system_templates(tmp_path, monkeypatch):
manager = WorkspaceManager(project_root=tmp_path)
manager.initialize_default_assets(
config_name="demo",
agent_ids=["portfolio_manager"],
analyst_personas={},
)
from backend.agents import prompt_factory
monkeypatch.setattr(
prompt_factory,
"SkillsManager",
lambda: SkillsManager(project_root=tmp_path),
)
prompt = build_agent_system_prompt(
agent_id="portfolio_manager",
config_name="demo",
toolkit=_DummyToolkit(),
)
assert "投资组合经理" in prompt
assert "使用 `make_decision` 工具记录每个股票的最终决策" in prompt
def test_skills_manager_applies_agent_level_skill_toggles(tmp_path):
builtin_root = tmp_path / "backend" / "skills" / "builtin"
for skill_name in ("risk_review", "extra_guard"):
skill_dir = builtin_root / skill_name
skill_dir.mkdir(parents=True, exist_ok=True)
(skill_dir / "SKILL.md").write_text(
f"# {skill_name}\n",
encoding="utf-8",
)
manager = WorkspaceManager(project_root=tmp_path)
manager.initialize_default_assets(
config_name="demo",
agent_ids=["risk_manager"],
analyst_personas={},
)
asset_dir = tmp_path / "runs" / "demo" / "agents" / "risk_manager"
(asset_dir / "agent.yaml").write_text(
"enabled_skills:\n"
" - extra_guard\n"
"disabled_skills:\n"
" - risk_review\n",
encoding="utf-8",
)
skills_manager = SkillsManager(project_root=tmp_path)
active_map = skills_manager.prepare_active_skills(
config_name="demo",
agent_defaults={"risk_manager": ["risk_review"]},
)
active_dirs = active_map["risk_manager"]
assert [path.name for path in active_dirs] == ["extra_guard"]
assert (asset_dir / "skills" / "installed" / "extra_guard" / "SKILL.md").exists()
assert (asset_dir / "skills" / "active" / "extra_guard" / "SKILL.md").exists()
assert (asset_dir / "skills" / "disabled" / "risk_review" / "SKILL.md").exists()
assert not (asset_dir / "skills" / "active" / "risk_review").exists()
def test_agent_local_skill_is_activated_from_agent_workspace(tmp_path):
manager = WorkspaceManager(project_root=tmp_path)
manager.initialize_default_assets(
config_name="demo",
agent_ids=["risk_manager"],
analyst_personas={},
)
asset_dir = tmp_path / "runs" / "demo" / "agents" / "risk_manager"
local_skill = asset_dir / "skills" / "local" / "local_guard"
local_skill.mkdir(parents=True, exist_ok=True)
(local_skill / "SKILL.md").write_text(
"---\nname: 本地风控\ndescription: local skill\nversion: 1.0.0\n---\n",
encoding="utf-8",
)
skills_manager = SkillsManager(project_root=tmp_path)
active_map = skills_manager.prepare_active_skills(
config_name="demo",
agent_defaults={"risk_manager": []},
)
assert [path.name for path in active_map["risk_manager"]] == ["local_guard"]
assert (asset_dir / "skills" / "active" / "local_guard" / "SKILL.md").exists()
def test_prompt_includes_active_skill_metadata_summary(tmp_path, monkeypatch):
builtin_root = tmp_path / "backend" / "skills" / "builtin"
skill_dir = builtin_root / "extra_guard"
skill_dir.mkdir(parents=True, exist_ok=True)
(skill_dir / "SKILL.md").write_text(
"---\n"
"name: extra_guard\n"
"description: This skill should be used when the user asks to \"run a risk check\".\n"
"version: 1.0.0\n"
"tools:\n"
" - risk_ops\n"
"---\n\n"
"# Extra Guard\n",
encoding="utf-8",
)
manager = WorkspaceManager(project_root=tmp_path)
manager.initialize_default_assets(
config_name="demo",
agent_ids=["risk_manager"],
analyst_personas={},
)
asset_dir = tmp_path / "runs" / "demo" / "agents" / "risk_manager"
(asset_dir / "agent.yaml").write_text(
"enabled_skills:\n"
" - extra_guard\n",
encoding="utf-8",
)
skills_manager = SkillsManager(project_root=tmp_path)
skills_manager.prepare_active_skills(
config_name="demo",
agent_defaults={"risk_manager": []},
)
from backend.agents import prompt_factory
monkeypatch.setattr(
prompt_factory,
"SkillsManager",
lambda: SkillsManager(project_root=tmp_path),
)
prompt = build_agent_system_prompt(
agent_id="risk_manager",
config_name="demo",
toolkit=_DummyToolkit(),
)
assert "Active Skill Catalog" in prompt
assert "This skill should be used when the user asks to \"run a risk check\"." in prompt
assert "version: 1.0.0" in prompt
assert "risk_ops" not in prompt