From dd89d16ec7d3356062bd9ea75a981693e626ebd9 Mon Sep 17 00:00:00 2001 From: AWUQAQ <257249127+AWUQAQ@users.noreply.github.com> Date: Sun, 13 Sep 2026 22:15:41 +0800 Subject: [PATCH] fix: clear skill search index when the catalog becomes empty --- ms_agent/skill/search.py | 2 ++ tests/skills/test_skill_features.py | 56 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/ms_agent/skill/search.py b/ms_agent/skill/search.py index e725c140d..45faca62a 100644 --- a/ms_agent/skill/search.py +++ b/ms_agent/skill/search.py @@ -85,4 +85,6 @@ def _ensure_indexed(self) -> None: if docs: self._retriever.index(docs, ids) + else: + self._retriever.reset() self._index_version = current_version diff --git a/tests/skills/test_skill_features.py b/tests/skills/test_skill_features.py index 28281a9fc..fb25fedef 100644 --- a/tests/skills/test_skill_features.py +++ b/tests/skills/test_skill_features.py @@ -311,6 +311,62 @@ def test_skills_list_with_query(self): self.assertEqual(result["skills"][0]["skill_id"], "paper-finder") self.assertIn("relevance_score", result["skills"][0]) + def test_search_after_disabling_all_skills(self): + from ms_agent.skill.search import SkillSearchEngine + engine = SkillSearchEngine(self.catalog, backend='bm25') + self.assertTrue(engine.search("papers")) + + for skill_id in list(self.catalog.get_enabled_skills()): + self.catalog.disable_skill(skill_id) + + self.assertEqual(engine.search("papers"), []) + self.assertEqual(engine.search("papers"), []) + + self.catalog.enable_skill("paper-finder") + self.assertEqual( + [sid for sid, _ in engine.search("papers")], ["paper-finder"]) + + def test_search_after_removing_all_skills(self): + from ms_agent.skill.search import SkillSearchEngine + engine = SkillSearchEngine(self.catalog, backend='bm25') + self.assertTrue(engine.search("papers")) + + for skill_id in list(self.catalog.get_enabled_skills()): + self.catalog.remove_skill(skill_id) + + self.assertEqual(engine.search("papers"), []) + self.assertEqual(engine.search("papers"), []) + + skill_dir = _make_skill_dir( + self.tmp, "new-papers", "New Papers", "Find research papers") + self.catalog.add_skill(str(skill_dir)) + self.assertEqual( + [sid for sid, _ in engine.search("papers")], ["new-papers"]) + + def test_empty_catalog_clears_hybrid_retrievers(self): + from ms_agent.retriever.bm25 import BM25Retriever + from ms_agent.retriever.hybrid import HybridRetriever + from ms_agent.skill.search import SkillSearchEngine + + # Exercise composite index reset without downloading embedding models. + retrievers = [BM25Retriever(), BM25Retriever()] + hybrid = HybridRetriever(retrievers) + with patch.object(SkillSearchEngine, '_build_retriever', + return_value=hybrid): + engine = SkillSearchEngine(self.catalog, backend='hybrid') + self.assertTrue(engine.search("papers")) + + for skill_id in list(self.catalog.get_enabled_skills()): + self.catalog.disable_skill(skill_id) + + self.assertEqual(engine.search("papers"), []) + for retriever in retrievers: + self.assertEqual(retriever.search("papers"), []) + + self.catalog.enable_skill("paper-finder") + self.assertEqual( + [sid for sid, _ in engine.search("papers")], ["paper-finder"]) + def test_skills_list_with_limit(self): from ms_agent.skill.skill_tools import SkillToolSet ts = SkillToolSet(DictConfig({}), self.catalog)