50 lines
1.5 KiB
Python
50 lines
1.5 KiB
Python
"""Meta-skill: create multi-step skills at runtime."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import textwrap
|
|
from pathlib import Path
|
|
|
|
from . import tool
|
|
|
|
|
|
@tool("build_skill", "Create a new multi-step skill from a description", category="meta")
|
|
def build_skill(name: str, description: str, steps: str, ctx: dict = None) -> str:
|
|
"""Generate a new skill and save it to the skills directory.
|
|
|
|
Args:
|
|
name: Skill name (snake_case)
|
|
description: What the skill does
|
|
steps: Python code implementing the skill steps (must use @skill decorator)
|
|
"""
|
|
if not name.isidentifier():
|
|
return f"Invalid skill name: {name}. Must be a valid Python identifier."
|
|
|
|
if not ctx or not ctx.get("config"):
|
|
return "Config context not available."
|
|
|
|
skills_dir = ctx["config"].skills_dir
|
|
skills_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
module_code = textwrap.dedent(f'''\
|
|
"""Auto-generated skill: {description}"""
|
|
from __future__ import annotations
|
|
from cheddahbot.skills import skill
|
|
|
|
{steps}
|
|
''')
|
|
|
|
file_path = skills_dir / f"{name}.py"
|
|
if file_path.exists():
|
|
return f"Skill '{name}' already exists. Choose a different name."
|
|
|
|
file_path.write_text(module_code, encoding="utf-8")
|
|
|
|
# Try to load it
|
|
try:
|
|
from cheddahbot.skills import load_skill
|
|
load_skill(file_path)
|
|
return f"Skill '{name}' created at {file_path}"
|
|
except Exception as e:
|
|
return f"Skill created at {file_path} but failed to load: {e}"
|