Files
JARVIS/backend/app/agents/skills/registry.py
WIN-JHFT4D3SIVT\caoxiaozhu a3fe4d24fc feat(agents): Phase 7-10 hook system, plugins, skills, orchestration
Phase 7: Built-in Hooks (audit_log, dangerous_confirmation, security_scan)
Phase 8: Plugin system (PluginManager, PluginSandbox, PluginManifest)
Phase 9: Skills registry (SkillRegistry, local/plugin/MCP loaders)
Phase 10: TeamLeader, RemoteTransport, BackgroundTaskManager
2026-04-04 22:56:27 +08:00

134 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Skills 注册表 - Phase 9.1"""
import os
from typing import Any
from app.agents.skills.metadata import SkillMetadata
from app.agents.skills.loaders.local_loader import LocalSkillLoader
class SkillRegistry:
"""Skills 注册表
管理所有 Skills 的注册、发现和加载。
"""
def __init__(self):
self._skills: dict[str, SkillMetadata] = {}
self._loaders: list[Any] = []
def load_all(self, skills_dir: str | None = None) -> int:
"""加载所有 Skills
Args:
skills_dir: Skills 目录None 则使用默认目录
Returns:
加载的 Skill 数量
"""
if skills_dir is None:
skills_dir = os.path.join(
os.path.dirname(__file__), "..", "..", "..", ".claude", "skills"
)
count = 0
# 本地加载器
local_loader = LocalSkillLoader(skills_dir)
local_skills = local_loader.load_all()
for skill in local_skills:
self.register(skill)
count += 1
# 插件加载器
for loader in self._loaders:
try:
external_skills = loader.load_all()
for skill in external_skills:
self.register(skill)
count += 1
except Exception:
pass
return count
def register(self, skill: SkillMetadata) -> None:
"""注册 Skill"""
self._skills[skill.name] = skill
def unregister(self, name: str) -> bool:
"""注销 Skill"""
if name in self._skills:
del self._skills[name]
return True
return False
def get_skill(self, name: str) -> SkillMetadata | None:
"""获取 Skill"""
return self._skills.get(name)
def search(self, query: str) -> list[SkillMetadata]:
"""搜索 Skills
Args:
query: 搜索关键词
Returns:
匹配的 Skills 列表
"""
query_lower = query.lower()
results = []
for skill in self._skills.values():
if not skill.enabled:
continue
# 匹配名称、描述、标签
if (
query_lower in skill.name.lower()
or query_lower in skill.description.lower()
or any(query_lower in tag.lower() for tag in skill.tags)
or any(query_lower in trigger.lower() for trigger in skill.triggers)
):
results.append(skill)
return results
def get_skill_context(self, names: list[str]) -> str:
"""获取 Skill 上下文
Args:
names: Skill 名称列表
Returns:
拼接的 Skill 内容
"""
contexts = []
for name in names:
skill = self._skills.get(name)
if skill and skill.enabled:
contexts.append(f"# {skill.name}\n\n{skill.content}")
return "\n\n---\n\n".join(contexts)
def add_loader(self, loader: Any) -> None:
"""添加加载器"""
self._loaders.append(loader)
def list_all(self) -> list[SkillMetadata]:
"""列出所有 Skills"""
return list(self._skills.values())
# 全局单例
_registry: SkillRegistry | None = None
def get_skill_registry() -> SkillRegistry:
"""获取全局 Skills 注册表"""
global _registry
if _registry is None:
_registry = SkillRegistry()
return _registry