tiphys.tools.skills

Skill-related tools for agents.

Provides tools for reading and listing available skills.

 1"""
 2Skill-related tools for agents.
 3
 4Provides tools for reading and listing available skills.
 5"""
 6
 7from tiphys.config import load_config
 8from tiphys.skills import SkillLoader, format_skill_index
 9from tiphys.tools.base import ToolDefinition, tool
10
11# Global skill loader instance
12_skill_loader: SkillLoader | None = None
13
14
15def get_skill_loader() -> SkillLoader:
16    """Get the global skill loader instance."""
17    global _skill_loader
18    if _skill_loader is None:
19        config = load_config()
20        _skill_loader = SkillLoader(config.skills_dir)
21    return _skill_loader
22
23
24@tool(
25    name="list_skills",
26    description="List all available skills. Returns a formatted index of skills the agent can read.",
27)
28async def list_skills() -> str:
29    """
30    List all available skills.
31
32    Returns:
33        Formatted list of available skills with descriptions.
34    """
35    loader = get_skill_loader()
36    skills = loader.get_index()
37
38    if not skills:
39        return "No skills are currently available in the skills directory."
40
41    return format_skill_index(skills)
42
43
44@tool(
45    name="read_skill",
46    description="Read a skill file by name to learn its content. Use list_skills first to see available skills.",
47)
48async def read_skill(name: str) -> str:
49    """
50    Read a skill by name.
51
52    Args:
53        name: The skill name (filename without .md extension).
54
55    Returns:
56        The skill content or an error message.
57    """
58    loader = get_skill_loader()
59    skill = loader.load(name)
60
61    if not skill:
62        # Try to provide helpful suggestions
63        available = loader.get_index()
64        if available:
65            names = [s.name for s in available]
66            suggestions = ", ".join(names[:5])
67            return f"Error: Skill '{name}' not found. Available skills: {suggestions}"
68        return f"Error: Skill '{name}' not found. No skills are currently available."
69
70    return f"# {skill.metadata.title}\n\n{skill.content}"
71
72
73def get_skill_tools() -> list[ToolDefinition]:
74    """Get all skill-related tool definitions."""
75    tools: list[ToolDefinition] = []
76
77    for func in [list_skills, read_skill]:
78        if hasattr(func, "_tool_definition"):
79            tools.append(func._tool_definition)
80
81    return tools
def get_skill_loader() -> tiphys.skills.SkillLoader:
16def get_skill_loader() -> SkillLoader:
17    """Get the global skill loader instance."""
18    global _skill_loader
19    if _skill_loader is None:
20        config = load_config()
21        _skill_loader = SkillLoader(config.skills_dir)
22    return _skill_loader

Get the global skill loader instance.

@tool(name='list_skills', description='List all available skills. Returns a formatted index of skills the agent can read.')
async def list_skills() -> str:
25@tool(
26    name="list_skills",
27    description="List all available skills. Returns a formatted index of skills the agent can read.",
28)
29async def list_skills() -> str:
30    """
31    List all available skills.
32
33    Returns:
34        Formatted list of available skills with descriptions.
35    """
36    loader = get_skill_loader()
37    skills = loader.get_index()
38
39    if not skills:
40        return "No skills are currently available in the skills directory."
41
42    return format_skill_index(skills)

List all available skills.

Returns: Formatted list of available skills with descriptions.

@tool(name='read_skill', description='Read a skill file by name to learn its content. Use list_skills first to see available skills.')
async def read_skill(name: str) -> str:
45@tool(
46    name="read_skill",
47    description="Read a skill file by name to learn its content. Use list_skills first to see available skills.",
48)
49async def read_skill(name: str) -> str:
50    """
51    Read a skill by name.
52
53    Args:
54        name: The skill name (filename without .md extension).
55
56    Returns:
57        The skill content or an error message.
58    """
59    loader = get_skill_loader()
60    skill = loader.load(name)
61
62    if not skill:
63        # Try to provide helpful suggestions
64        available = loader.get_index()
65        if available:
66            names = [s.name for s in available]
67            suggestions = ", ".join(names[:5])
68            return f"Error: Skill '{name}' not found. Available skills: {suggestions}"
69        return f"Error: Skill '{name}' not found. No skills are currently available."
70
71    return f"# {skill.metadata.title}\n\n{skill.content}"

Read a skill by name.

Args: name: The skill name (filename without .md extension).

Returns: The skill content or an error message.

def get_skill_tools() -> list[tiphys.tools.base.ToolDefinition]:
74def get_skill_tools() -> list[ToolDefinition]:
75    """Get all skill-related tool definitions."""
76    tools: list[ToolDefinition] = []
77
78    for func in [list_skills, read_skill]:
79        if hasattr(func, "_tool_definition"):
80            tools.append(func._tool_definition)
81
82    return tools

Get all skill-related tool definitions.