self-trained2 / agent /tools /skill_tools.py
DeepImagix's picture
Upload 2 files
71eac6c verified
Raw History Blame Contribute Delete
4.38 kB
"""
NeuraPrompt — Skill tools (list / load / save)
=============================================
Sync functions; agent wraps them with asyncio.to_thread via the registry.
"""
from __future__ import annotations
import logging
from typing import Optional
log = logging.getLogger("agent.tools.skills")
def _builtins():
try:
from ..skills_catalog import BUILTIN_SKILLS, get_builtin
except ImportError:
from skills_catalog import BUILTIN_SKILLS, get_builtin # type: ignore
return BUILTIN_SKILLS, get_builtin
def _memory():
try:
from .. import agent_memory as mem
except ImportError:
import agent_memory as mem # type: ignore
return mem
def list_skills(user_id: str = "") -> str:
"""List builtin + user skill names with when_to_use hints."""
BUILTIN_SKILLS, _ = _builtins()
lines = ["## Builtin skills"]
for sk in BUILTIN_SKILLS:
lines.append(f"- **{sk['name']}**: {sk.get('when_to_use', '')}")
if user_id:
mem = _memory()
try:
# Prefer richer listing if available
db = mem._get_db() if hasattr(mem, "_get_db") else None
if db is not None:
skills = list(
db.skills.find(
{"user_id": user_id},
{"skill_name": 1, "when_to_use": 1, "skill_description": 1, "_id": 0},
)
)
if skills:
lines.append("\n## Your learned skills")
for s in skills[:20]:
name = s.get("skill_name", "?")
when = s.get("when_to_use") or s.get("skill_description", "")[:120]
lines.append(f"- **{name}**: {when}")
else:
names = mem.get_skills_list(user_id) or []
if names:
lines.append("\n## Your learned skills")
for n in names:
lines.append(f"- **{n}**")
except Exception as e:
log.warning(f"[skill_tools] list user skills failed: {e}")
return "\n".join(lines)
def load_skill(name: str, user_id: str = "") -> str:
"""Load full skill body: builtins first, then Mongo user skills."""
if not name or not str(name).strip():
return "Error: skill name is required."
_, get_builtin = _builtins()
builtin = get_builtin(name)
if builtin:
return (
f"# Skill: {builtin['name']}\n"
f"**When to use:** {builtin.get('when_to_use', '')}\n\n"
f"{builtin.get('body', '')}"
)
if user_id:
mem = _memory()
try:
detail = None
if hasattr(mem, "get_skill_detail"):
detail = mem.get_skill_detail(user_id, name)
if detail:
return f"# Skill: {name}\n\n{detail}"
except Exception as e:
log.warning(f"[skill_tools] load user skill failed: {e}")
return f"Skill '{name}' not found. Use list_skills to see available skills."
def save_user_skill(
user_id: str,
name: str,
when_to_use: str = "",
body: str = "",
) -> str:
"""Save / update a user skill with richer fields."""
if not user_id:
return "Error: user_id is required to save a skill."
if not name or not name.strip():
return "Error: skill name is required."
mem = _memory()
try:
if hasattr(mem, "save_skill"):
# Prefer enhanced signature
try:
is_new = mem.save_skill(
user_id,
name.strip(),
body or when_to_use or name,
when_to_use=when_to_use or "",
skill_body=body or "",
)
except TypeError:
is_new = mem.save_skill(
user_id,
name.strip(),
body or when_to_use or name,
)
if is_new:
return f"Saved new skill '{name}'."
return f"Updated skill '{name}'."
return "Error: skill storage unavailable."
except Exception as e:
log.warning(f"[skill_tools] save_user_skill failed: {e}")
return f"Error saving skill: {e}"
__all__ = ["list_skills", "load_skill", "save_user_skill"]