feat: init sproutclaw-web — Go+Gin backend + React frontend
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
72
backend/internal/services/skills.go
Normal file
72
backend/internal/services/skills.go
Normal file
@@ -0,0 +1,72 @@
|
||||
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,
|
||||
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))
|
||||
}
|
||||
Reference in New Issue
Block a user