mirror of
https://github.com/HKUDS/OpenSpace.git
synced 2026-08-28 05:15:00 +00:00
Refresh local registry for local skill search
This commit is contained in:
parent
f4451aa0ac
commit
fb02862d44
2 changed files with 71 additions and 6 deletions
|
|
@ -119,7 +119,6 @@ mcp = FastMCP("OpenSpace", **_fastmcp_kwargs)
|
|||
_openspace_instance = None
|
||||
_openspace_lock = asyncio.Lock()
|
||||
_standalone_store = None
|
||||
_local_skill_registry = None
|
||||
|
||||
# Internal state: tracks bot skill directories already registered this session.
|
||||
_registered_skill_dirs: set = set()
|
||||
|
|
@ -205,11 +204,9 @@ def _get_local_skill_registry():
|
|||
This avoids initializing the full OpenSpace engine when callers only
|
||||
want to inspect local skills. It mirrors the skill directory discovery
|
||||
order used by the full engine, but skips LLM / provider startup.
|
||||
The registry is rebuilt per call so later local searches can see
|
||||
newly added skills without requiring a process restart.
|
||||
"""
|
||||
global _local_skill_registry
|
||||
if _local_skill_registry is not None:
|
||||
return _local_skill_registry
|
||||
|
||||
from openspace.config import get_config
|
||||
from openspace.skill_engine import SkillRegistry
|
||||
|
||||
|
|
@ -253,7 +250,6 @@ def _get_local_skill_registry():
|
|||
|
||||
registry = SkillRegistry(skill_dirs=skill_paths)
|
||||
registry.discover()
|
||||
_local_skill_registry = registry
|
||||
return registry
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,3 +47,72 @@ Find me when querying demo local skill.
|
|||
item["name"] == "Demo Local Skill"
|
||||
for item in payload["results"]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_local_search_skills_refreshes_registry_between_calls(monkeypatch, tmp_path):
|
||||
skill_root = tmp_path / "skills"
|
||||
first_skill_dir = skill_root / "first-local-skill"
|
||||
first_skill_dir.mkdir(parents=True)
|
||||
(first_skill_dir / "SKILL.md").write_text(
|
||||
"""---
|
||||
name: First Local Skill
|
||||
description: First local skill for cache regression coverage
|
||||
---
|
||||
|
||||
First local skill content.
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
async def forbidden_get_openspace():
|
||||
pytest.fail("_get_openspace should not run for source='local'")
|
||||
|
||||
monkeypatch.setenv("OPENSPACE_HOST_SKILL_DIRS", str(skill_root))
|
||||
monkeypatch.delenv("OPENROUTER_API_KEY", raising=False)
|
||||
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
||||
monkeypatch.delenv("OPENAI_BASE_URL", raising=False)
|
||||
monkeypatch.setattr(mcp_server, "_get_openspace", forbidden_get_openspace)
|
||||
monkeypatch.setattr(
|
||||
"openspace.cloud.embedding.generate_embedding",
|
||||
lambda text, api_key=None: None,
|
||||
)
|
||||
|
||||
first_response = await mcp_server.search_skills(
|
||||
query="first local skill",
|
||||
source="local",
|
||||
limit=5,
|
||||
auto_import=False,
|
||||
)
|
||||
|
||||
first_payload = json.loads(first_response)
|
||||
assert any(
|
||||
item["name"] == "First Local Skill"
|
||||
for item in first_payload["results"]
|
||||
)
|
||||
|
||||
second_skill_dir = skill_root / "second-local-skill"
|
||||
second_skill_dir.mkdir(parents=True)
|
||||
(second_skill_dir / "SKILL.md").write_text(
|
||||
"""---
|
||||
name: Second Local Skill
|
||||
description: Second local skill created after the first search
|
||||
---
|
||||
|
||||
Second local skill content.
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
second_response = await mcp_server.search_skills(
|
||||
query="second local skill",
|
||||
source="local",
|
||||
limit=5,
|
||||
auto_import=False,
|
||||
)
|
||||
|
||||
second_payload = json.loads(second_response)
|
||||
assert any(
|
||||
item["name"] == "Second Local Skill"
|
||||
for item in second_payload["results"]
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue