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
134 lines
3.4 KiB
Python
134 lines
3.4 KiB
Python
"""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
|