File size: 9,804 Bytes
1397957
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
"""Skill tool - loads detailed instructions for specific tasks."""
from typing import Dict, Any, List, Optional
from pydantic import BaseModel, Field

from .tool import BaseTool, ToolResult, ToolContext


class SkillInfo(BaseModel):
    """Information about a skill."""
    name: str
    description: str
    content: str


# Built-in skills registry
_skills: Dict[str, SkillInfo] = {}


def register_skill(skill: SkillInfo) -> None:
    """Register a skill."""
    _skills[skill.name] = skill


def get_skill(name: str) -> Optional[SkillInfo]:
    """Get a skill by name."""
    return _skills.get(name)


def list_skills() -> List[SkillInfo]:
    """List all registered skills."""
    return list(_skills.values())


# Built-in default skills
DEFAULT_SKILLS = [
    SkillInfo(
        name="web-research",
        description="Comprehensive web research methodology for gathering information from multiple sources",
        content="""# Web Research Skill

## Purpose
Guide for conducting thorough web research to answer questions or gather information.

## Methodology

### 1. Query Formulation
- Break down complex questions into specific search queries
- Use different phrasings to get diverse results
- Include domain-specific terms when relevant

### 2. Source Evaluation
- Prioritize authoritative sources (official docs, reputable publications)
- Cross-reference information across multiple sources
- Note publication dates for time-sensitive information

### 3. Information Synthesis
- Compile findings from multiple sources
- Identify consensus vs. conflicting information
- Summarize key points clearly

### 4. Citation
- Always provide source URLs
- Note when information might be outdated

## Tools to Use
- `websearch`: For finding relevant pages
- `webfetch`: For extracting content from specific URLs

## Best Practices
- Start broad, then narrow down
- Use quotes for exact phrases
- Filter by date when freshness matters
- Verify claims with multiple sources
"""
    ),
    SkillInfo(
        name="code-explanation",
        description="Methodology for explaining code clearly to users of varying skill levels",
        content="""# Code Explanation Skill

## Purpose
Guide for explaining code in a clear, educational manner.

## Approach

### 1. Assess Context
- Determine user's apparent skill level
- Identify what aspect they're asking about
- Note any specific confusion points

### 2. Structure Explanation
- Start with high-level overview (what does it do?)
- Break down into logical sections
- Explain each component's purpose

### 3. Use Analogies
- Relate concepts to familiar ideas
- Use real-world metaphors when helpful
- Avoid overly technical jargon initially

### 4. Provide Examples
- Show simple examples first
- Build up to complex cases
- Include edge cases when relevant

### 5. Verify Understanding
- Use the question tool to check comprehension
- Offer to elaborate on specific parts
- Provide additional resources if needed

## Best Practices
- Don't assume prior knowledge
- Explain "why" not just "what"
- Use code comments effectively
- Highlight common pitfalls
"""
    ),
    SkillInfo(
        name="api-integration",
        description="Best practices for integrating with external APIs",
        content="""# API Integration Skill

## Purpose
Guide for properly integrating with external APIs.

## Key Considerations

### 1. Authentication
- Store API keys securely (environment variables)
- Never hardcode credentials
- Handle token refresh if applicable

### 2. Error Handling
- Implement retry logic for transient failures
- Handle rate limiting gracefully
- Log errors with context

### 3. Request Best Practices
- Set appropriate timeouts
- Use connection pooling
- Implement circuit breakers for resilience

### 4. Response Handling
- Validate response schemas
- Handle pagination properly
- Cache responses when appropriate

### 5. Testing
- Mock API responses in tests
- Test error scenarios
- Verify rate limit handling

## Common Patterns

```python
# Example: Robust API call
async def call_api(url, retries=3):
    for attempt in range(retries):
        try:
            response = await httpx.get(url, timeout=30)
            response.raise_for_status()
            return response.json()
        except httpx.HTTPStatusError as e:
            if e.response.status_code == 429:
                await asyncio.sleep(2 ** attempt)
            elif e.response.status_code >= 500:
                await asyncio.sleep(1)
            else:
                raise
    raise Exception("Max retries exceeded")
```
"""
    ),
    SkillInfo(
        name="debugging",
        description="Systematic approach to debugging problems",
        content="""# Debugging Skill

## Purpose
Systematic methodology for identifying and fixing bugs.

## Process

### 1. Reproduce the Issue
- Get exact steps to reproduce
- Note environment details
- Identify when it started happening

### 2. Gather Information
- Check error messages and stack traces
- Review recent changes
- Check logs for anomalies

### 3. Form Hypotheses
- List possible causes
- Rank by likelihood
- Consider recent changes first

### 4. Test Hypotheses
- Start with most likely cause
- Make minimal changes to test
- Verify each hypothesis before moving on

### 5. Implement Fix
- Fix root cause, not symptoms
- Add tests to prevent regression
- Document the fix

### 6. Verify Fix
- Confirm original issue is resolved
- Check for side effects
- Test related functionality

## Debugging Questions
- What changed recently?
- Does it happen consistently?
- What's different when it works?
- What are the exact inputs?

## Tools
- Use print/log statements strategically
- Leverage debuggers when available
- Check version differences
"""
    ),
    SkillInfo(
        name="task-planning",
        description="Breaking down complex tasks into manageable steps",
        content="""# Task Planning Skill

## Purpose
Guide for decomposing complex tasks into actionable steps.

## Methodology

### 1. Understand the Goal
- Clarify the end objective
- Identify success criteria
- Note any constraints

### 2. Identify Components
- Break into major phases
- List dependencies between parts
- Identify parallel vs. sequential work

### 3. Create Action Items
- Make each item specific and actionable
- Estimate effort/complexity
- Assign priorities

### 4. Sequence Work
- Order by dependencies
- Front-load risky items
- Plan for blockers

### 5. Track Progress
- Use todo tool to track items
- Update status as work progresses
- Re-plan when needed

## Best Practices
- Start with end goal in mind
- Keep items small (< 1 hour ideal)
- Include verification steps
- Plan for error cases

## Example Structure
1. Research & understand requirements
2. Design approach
3. Implement core functionality
4. Add error handling
5. Test thoroughly
6. Document changes
"""
    ),
]


def _get_skill_description(skills: List[SkillInfo]) -> str:
    """Generate description with available skills."""
    if not skills:
        return "Load a skill to get detailed instructions for a specific task. No skills are currently available."
    
    lines = [
        "Load a skill to get detailed instructions for a specific task.",
        "Skills provide specialized knowledge and step-by-step guidance.",
        "Use this when a task matches an available skill's description.",
        "",
        "<available_skills>",
    ]
    
    for skill in skills:
        lines.extend([
            f"  <skill>",
            f"    <name>{skill.name}</name>",
            f"    <description>{skill.description}</description>",
            f"  </skill>",
        ])
    
    lines.append("</available_skills>")
    
    return "\n".join(lines)


class SkillTool(BaseTool):
    """Tool for loading skill instructions."""
    
    def __init__(self, additional_skills: Optional[List[SkillInfo]] = None):
        """Initialize with optional additional skills."""
        # Register default skills
        for skill in DEFAULT_SKILLS:
            register_skill(skill)
        
        # Register additional skills if provided
        if additional_skills:
            for skill in additional_skills:
                register_skill(skill)
    
    @property
    def id(self) -> str:
        return "skill"
    
    @property
    def description(self) -> str:
        return _get_skill_description(list_skills())
    
    @property
    def parameters(self) -> Dict[str, Any]:
        skill_names = [s.name for s in list_skills()]
        examples = ", ".join(f"'{n}'" for n in skill_names[:3])
        hint = f" (e.g., {examples}, ...)" if examples else ""
        
        return {
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "description": f"The skill identifier from available_skills{hint}",
                    "enum": skill_names if skill_names else None
                }
            },
            "required": ["name"]
        }
    
    async def execute(self, args: Dict[str, Any], ctx: ToolContext) -> ToolResult:
        skill_name = args.get("name", "")
        
        skill = get_skill(skill_name)
        
        if not skill:
            available = ", ".join(s.name for s in list_skills())
            return ToolResult(
                title=f"Skill not found: {skill_name}",
                output=f'Skill "{skill_name}" not found. Available skills: {available or "none"}',
                metadata={"error": True}
            )
        
        output = f"""## Skill: {skill.name}

**Description**: {skill.description}

{skill.content}
"""
        
        return ToolResult(
            title=f"Loaded skill: {skill.name}",
            output=output,
            metadata={"name": skill.name}
        )