Add new skills descriptions and enhance skills tool functionality
- Added detailed descriptions for new skills categories: Machine Learning Operations and Note Taking. - Introduced a new Obsidian skill with commands for reading, listing, searching, creating, and appending notes. - Enhanced the skills tool to load and display category descriptions from DESCRIPTION.md files, improving user guidance and discovery of available skills.
This commit is contained in:
parent
32254d3010
commit
8f5f99c22a
5 changed files with 149 additions and 7 deletions
20
TODO.md
20
TODO.md
|
|
@ -276,6 +276,26 @@ These items need to be addressed ASAP:
|
||||||
|
|
||||||
### Medium-Impact
|
### Medium-Impact
|
||||||
|
|
||||||
|
- [ ] **Canvas / Visual Workspace** 🖼️
|
||||||
|
- Agent-controlled visual panel for rendering interactive UI
|
||||||
|
- Inspired by OpenClaw's Canvas feature
|
||||||
|
- **Capabilities:**
|
||||||
|
- `present` / `hide` - Show/hide the canvas panel
|
||||||
|
- `navigate` - Load HTML files or URLs into the canvas
|
||||||
|
- `eval` - Execute JavaScript in the canvas context
|
||||||
|
- `snapshot` - Capture the rendered UI as an image
|
||||||
|
- **Use cases:**
|
||||||
|
- Display generated HTML/CSS/JS previews
|
||||||
|
- Show interactive data visualizations (charts, graphs)
|
||||||
|
- Render diagrams (Mermaid → rendered output)
|
||||||
|
- Present structured information in rich format
|
||||||
|
- A2UI-style component system for structured agent UI
|
||||||
|
- **Implementation options:**
|
||||||
|
- Electron-based panel for CLI
|
||||||
|
- WebSocket-connected web app
|
||||||
|
- VS Code webview extension
|
||||||
|
- *Would let agent "show" things rather than just describe them*
|
||||||
|
|
||||||
- [ ] **Document Generation** 📄
|
- [ ] **Document Generation** 📄
|
||||||
- Create styled PDFs, Word docs, presentations
|
- Create styled PDFs, Word docs, presentations
|
||||||
- *Can do basic PDF via terminal tools, but limited*
|
- *Can do basic PDF via terminal tools, but limited*
|
||||||
|
|
|
||||||
3
skills/mlops/DESCRIPTION.md
Normal file
3
skills/mlops/DESCRIPTION.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
description: Knowledge and Tools for Machine Learning Operations - tools and frameworks for training, fine-tuning, deploying, and optimizing ML/AI models
|
||||||
|
---
|
||||||
3
skills/note-taking/DESCRIPTION.md
Normal file
3
skills/note-taking/DESCRIPTION.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
description: Note taking skills, to save information, assist with research, and collab on multi-session planning and information sharing.
|
||||||
|
---
|
||||||
57
skills/note-taking/obsidian/SKILL.md
Normal file
57
skills/note-taking/obsidian/SKILL.md
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
---
|
||||||
|
name: obsidian
|
||||||
|
description: Read, search, and create notes in the Obsidian vault.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Obsidian Vault
|
||||||
|
|
||||||
|
**Location:** `/home/teknium/Documents/Primary Vault`
|
||||||
|
|
||||||
|
Note: Path contains a space - always quote it.
|
||||||
|
|
||||||
|
## Read a note
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat "/home/teknium/Documents/Primary Vault/Note Name.md"
|
||||||
|
```
|
||||||
|
|
||||||
|
## List notes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# All notes
|
||||||
|
find "/home/teknium/Documents/Primary Vault" -name "*.md" -type f
|
||||||
|
|
||||||
|
# In a specific folder
|
||||||
|
ls "/home/teknium/Documents/Primary Vault/AI Research/"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Search
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# By filename
|
||||||
|
find "/home/teknium/Documents/Primary Vault" -name "*.md" -iname "*keyword*"
|
||||||
|
|
||||||
|
# By content
|
||||||
|
grep -rli "keyword" "/home/teknium/Documents/Primary Vault" --include="*.md"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create a note
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat > "/home/teknium/Documents/Primary Vault/New Note.md" << 'ENDNOTE'
|
||||||
|
# Title
|
||||||
|
|
||||||
|
Content here.
|
||||||
|
ENDNOTE
|
||||||
|
```
|
||||||
|
|
||||||
|
## Append to a note
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo "
|
||||||
|
New content here." >> "/home/teknium/Documents/Primary Vault/Existing Note.md"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Wikilinks
|
||||||
|
|
||||||
|
Obsidian links notes with `[[Note Name]]` syntax. When creating notes, use these to link related content.
|
||||||
|
|
@ -312,17 +312,56 @@ def _find_all_skills() -> List[Dict[str, Any]]:
|
||||||
return skills
|
return skills
|
||||||
|
|
||||||
|
|
||||||
|
def _load_category_description(category_dir: Path) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
Load category description from DESCRIPTION.md if it exists.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
category_dir: Path to the category directory
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Description string or None if not found
|
||||||
|
"""
|
||||||
|
desc_file = category_dir / "DESCRIPTION.md"
|
||||||
|
if not desc_file.exists():
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
content = desc_file.read_text(encoding='utf-8')
|
||||||
|
# Parse frontmatter if present
|
||||||
|
frontmatter, body = _parse_frontmatter(content)
|
||||||
|
|
||||||
|
# Prefer frontmatter description, fall back to first non-header line
|
||||||
|
description = frontmatter.get('description', '')
|
||||||
|
if not description:
|
||||||
|
for line in body.strip().split('\n'):
|
||||||
|
line = line.strip()
|
||||||
|
if line and not line.startswith('#'):
|
||||||
|
description = line
|
||||||
|
break
|
||||||
|
|
||||||
|
# Truncate to reasonable length
|
||||||
|
if len(description) > MAX_DESCRIPTION_LENGTH:
|
||||||
|
description = description[:MAX_DESCRIPTION_LENGTH - 3] + "..."
|
||||||
|
|
||||||
|
return description if description else None
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def skills_categories(task_id: str = None) -> str:
|
def skills_categories(task_id: str = None) -> str:
|
||||||
"""
|
"""
|
||||||
List available skill categories (progressive disclosure tier 0).
|
List available skill categories with descriptions (progressive disclosure tier 0).
|
||||||
|
|
||||||
Returns just category names for efficient discovery before filtering.
|
Returns category names and descriptions for efficient discovery before drilling down.
|
||||||
|
Categories can have a DESCRIPTION.md file with a description frontmatter field
|
||||||
|
or first paragraph to explain what skills are in that category.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
task_id: Optional task identifier (unused, for API consistency)
|
task_id: Optional task identifier (unused, for API consistency)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
JSON string with list of category names
|
JSON string with list of categories and their descriptions
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if not SKILLS_DIR.exists():
|
if not SKILLS_DIR.exists():
|
||||||
|
|
@ -333,16 +372,36 @@ def skills_categories(task_id: str = None) -> str:
|
||||||
}, ensure_ascii=False)
|
}, ensure_ascii=False)
|
||||||
|
|
||||||
# Scan for categories (top-level directories containing skills)
|
# Scan for categories (top-level directories containing skills)
|
||||||
categories = set()
|
category_dirs = {}
|
||||||
for skill_md in SKILLS_DIR.rglob("SKILL.md"):
|
for skill_md in SKILLS_DIR.rglob("SKILL.md"):
|
||||||
category = _get_category_from_path(skill_md)
|
category = _get_category_from_path(skill_md)
|
||||||
if category:
|
if category:
|
||||||
categories.add(category)
|
category_dir = SKILLS_DIR / category
|
||||||
|
if category not in category_dirs:
|
||||||
|
category_dirs[category] = category_dir
|
||||||
|
|
||||||
|
# Build category list with descriptions
|
||||||
|
categories = []
|
||||||
|
for name in sorted(category_dirs.keys()):
|
||||||
|
category_dir = category_dirs[name]
|
||||||
|
description = _load_category_description(category_dir)
|
||||||
|
|
||||||
|
# Count skills in this category
|
||||||
|
skill_count = sum(1 for _ in category_dir.rglob("SKILL.md"))
|
||||||
|
|
||||||
|
cat_entry = {
|
||||||
|
"name": name,
|
||||||
|
"skill_count": skill_count
|
||||||
|
}
|
||||||
|
if description:
|
||||||
|
cat_entry["description"] = description
|
||||||
|
|
||||||
|
categories.append(cat_entry)
|
||||||
|
|
||||||
return json.dumps({
|
return json.dumps({
|
||||||
"success": True,
|
"success": True,
|
||||||
"categories": sorted(categories),
|
"categories": categories,
|
||||||
"hint": "Use skills_list(category) to see skills in a category"
|
"hint": "If a category is relevant to your task, use skills_list with that category to see available skills"
|
||||||
}, ensure_ascii=False)
|
}, ensure_ascii=False)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue