"""技能进化运行时把涉及的技能名输出到日志。""" from __future__ import annotations import logging from deerflow.skills import curator _CURATOR_LOGGER = "deerflow.skills.curator" class TestCandidateSkillNames: def test_extracts_names_from_candidate_lines(self): text = "- alpha [state=active, use=1]\n- beta-skill [state=stale, use=0]" assert curator._candidate_skill_names(text) == ["alpha", "beta-skill"] def test_ignores_non_candidate_lines(self): # _render_candidate_list 无候选时返回的提示文本不应被误识别为技能名 assert curator._candidate_skill_names("No agent-created active skills found.") == [] def test_empty(self): assert curator._candidate_skill_names("") == [] class TestLogScannedSkills: def _patch_common(self, monkeypatch, entries: dict, owned=None) -> None: monkeypatch.setattr(curator, "_list_user_owned_skill_names", lambda uid: owned) monkeypatch.setattr("deerflow.skills.usage.agent_created_entries", lambda: entries) monkeypatch.setattr("deerflow.skills.curator_log.record", lambda *a, **k: None) def test_logs_and_returns_sorted_skill_names(self, monkeypatch, caplog): self._patch_common( monkeypatch, {"zeta": {"source": "agent"}, "alpha": {"source": "agent"}}, ) with caplog.at_level(logging.INFO, logger=_CURATOR_LOGGER): names = curator._log_scanned_skills("u1") assert names == ["alpha", "zeta"] assert "alpha" in caplog.text assert "zeta" in caplog.text def test_filters_to_owned_skills(self, monkeypatch, caplog): self._patch_common( monkeypatch, {"alpha": {"source": "agent"}, "beta": {"source": "agent"}}, owned={"alpha"}, ) with caplog.at_level(logging.INFO, logger=_CURATOR_LOGGER): names = curator._log_scanned_skills("u1") assert names == ["alpha"] def test_empty_skills(self, monkeypatch, caplog): self._patch_common(monkeypatch, {}) with caplog.at_level(logging.INFO, logger=_CURATOR_LOGGER): names = curator._log_scanned_skills("u1") assert names == []