"""skills_creator skill""" import json from pathlib import Path import shutil from typing import Any, Dict from src.ai.skills.base import Skill, SkillsManager, create_skill_template class SkillsCreatorSkill(Skill): """Provide tools to create and manage local skills from chat.""" def __init__(self): super().__init__() self.skills_root = Path("skills") self.protected_skills = {"skills_creator"} async def initialize(self): self.register_tool("create_skill", self.create_skill) self.register_tool("write_skill_main", self.write_skill_main) self.register_tool("update_skill_metadata", self.update_skill_metadata) self.register_tool("delete_skill", self.delete_skill) self.register_tool("load_skill", self.load_skill) self.register_tool("reload_skill", self.reload_skill) self.register_tool("list_skills", self.list_skills) def _skill_key(self, skill_name: str) -> str: return SkillsManager.normalize_skill_key(skill_name) def _skill_path(self, skill_name: str) -> Path: return self.skills_root / self._skill_key(skill_name) async def create_skill( self, skill_name: str, description: str = "custom skill", author: str = "chat_user", auto_load: bool = True, overwrite: bool = False, ) -> str: skill_key = self._skill_key(skill_name) skill_path = self._skill_path(skill_key) if skill_path.exists() and not overwrite: return f"技能已存在: {skill_key}" if skill_path.exists() and overwrite: shutil.rmtree(skill_path) create_skill_template(skill_key, self.skills_root, description=description, author=author) if auto_load and self.manager: await self.manager.load_skill(skill_key) return f"已创建技能: {skill_key}" async def write_skill_main(self, skill_name: str, code: str, auto_reload: bool = True) -> str: skill_key = self._skill_key(skill_name) skill_path = self._skill_path(skill_key) if not skill_path.exists(): return f"技能不存在: {skill_key}" main_file = skill_path / "main.py" main_file.write_text(code, encoding="utf-8") if auto_reload and self.manager: await self.manager.reload_skill(skill_key) return f"已更新技能代码: {skill_key}/main.py" async def update_skill_metadata(self, skill_name: str, fields: Dict[str, Any]) -> str: skill_key = self._skill_key(skill_name) skill_path = self._skill_path(skill_key) if not skill_path.exists(): return f"技能不存在: {skill_key}" metadata_file = skill_path / "skill.json" if metadata_file.exists(): metadata = json.loads(metadata_file.read_text(encoding="utf-8")) else: metadata = { "name": skill_key, "version": "1.0.0", "description": "", "author": "chat_user", "dependencies": [], "enabled": True, } for key, value in fields.items(): metadata[key] = value metadata.setdefault("name", skill_key) metadata.setdefault("version", "1.0.0") metadata.setdefault("description", "") metadata.setdefault("author", "chat_user") metadata.setdefault("dependencies", []) metadata.setdefault("enabled", True) metadata_file.write_text(json.dumps(metadata, ensure_ascii=False, indent=2), encoding="utf-8") return f"已更新技能元数据: {skill_key}/skill.json" async def delete_skill(self, skill_name: str, delete_files: bool = True) -> str: skill_key = self._skill_key(skill_name) if skill_key in self.protected_skills: return f"拒绝删除受保护技能: {skill_key}" if self.manager: removed = await self.manager.uninstall_skill(skill_key, delete_files=delete_files) return f"删除结果({skill_key}): {removed}" skill_path = self._skill_path(skill_key) if delete_files and skill_path.exists(): shutil.rmtree(skill_path) return f"已删除技能目录: {skill_key}" return f"技能不存在或未删除: {skill_key}" async def load_skill(self, skill_name: str) -> str: skill_key = self._skill_key(skill_name) if not self.manager: return "SkillsManager 不可用" success = await self.manager.load_skill(skill_key) return f"加载技能 {skill_key}: {success}" async def reload_skill(self, skill_name: str) -> str: skill_key = self._skill_key(skill_name) if not self.manager: return "SkillsManager 不可用" success = await self.manager.reload_skill(skill_key) return f"重载技能 {skill_key}: {success}" async def list_skills(self) -> str: if not self.manager: return "SkillsManager 不可用" payload = { "loaded": self.manager.list_skills(), "available": self.manager.list_available_skills(), } return json.dumps(payload, ensure_ascii=False) async def cleanup(self): pass