Files
sproutclaw-web/backend/internal/services/skills.go
2026-06-14 20:31:10 +08:00

74 lines
1.8 KiB
Go

package services
import (
"fmt"
"os"
"path/filepath"
"strings"
"sproutclaw-web/internal/models"
)
// ListSkills returns all skills (enabled and disabled) under agentDir.
func ListSkills(agentDir string) []models.SkillInfo {
var skills []models.SkillInfo
skills = append(skills, scanSkillsDir(filepath.Join(agentDir, "skills"), true)...)
skills = append(skills, scanSkillsDir(filepath.Join(agentDir, "skills-disabled"), false)...)
return skills
}
func scanSkillsDir(dir string, enabled bool) []models.SkillInfo {
entries, err := os.ReadDir(dir)
if err != nil {
return nil
}
var skills []models.SkillInfo
for _, e := range entries {
if !e.IsDir() {
continue
}
skillPath := filepath.Join(dir, e.Name())
name, desc := parseSkillMD(filepath.Join(skillPath, "SKILL.md"))
if name == "" {
name = e.Name()
}
skills = append(skills, models.SkillInfo{
Name: name,
Description: desc,
Enabled: enabled,
Toggleable: true,
Path: skillPath,
})
}
return skills
}
// ToggleSkill moves a skill between skills/ and skills-disabled/ directories.
func ToggleSkill(agentDir, skillPath string, enable bool) error {
skillsDir := filepath.Join(agentDir, "skills")
disabledDir := filepath.Join(agentDir, "skills-disabled")
if !isUnderDir(skillPath, skillsDir) && !isUnderDir(skillPath, disabledDir) {
return fmt.Errorf("skill path not in managed directories")
}
name := filepath.Base(skillPath)
var src, dst string
if enable {
src = filepath.Join(disabledDir, name)
dst = filepath.Join(skillsDir, name)
} else {
src = filepath.Join(skillsDir, name)
dst = filepath.Join(disabledDir, name)
}
if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
return err
}
return os.Rename(src, dst)
}
func isUnderDir(path, dir string) bool {
return strings.HasPrefix(filepath.Clean(path), filepath.Clean(dir))
}