admin 8dc496b626
Some checks failed
CI / test (push) Has been cancelled
Release / release (push) Failing after 4m36s
first commit
2026-03-08 15:40:34 +07:00

119 lines
2.6 KiB
Go

package skill
import (
"fmt"
"os"
"path/filepath"
"strings"
)
type Manager struct {
skills []*Skill
dirs []string
}
func NewManager(dir string) *Manager {
dirs := []string{}
if dir != "" {
dirs = append(dirs, dir)
} else {
if home, err := os.UserHomeDir(); err == nil {
dirs = append(dirs, filepath.Join(home, ".config", "ai-agent", "skills"))
}
}
return &Manager{dirs: dirs}
}
func (m *Manager) AddSearchPath(dir string) {
for _, d := range m.dirs {
if d == dir {
return
}
}
m.dirs = append(m.dirs, dir)
}
func (m *Manager) Names() []string {
var names []string
for _, s := range m.skills {
names = append(names, s.Name)
}
return names
}
func (m *Manager) LoadAll() error {
for _, dir := range m.dirs {
if err := m.loadFromDir(dir); err != nil {
return err
}
}
return nil
}
func (m *Manager) loadFromDir(dir string) error {
if dir == "" {
return nil
}
entries, err := os.ReadDir(dir)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return fmt.Errorf("read skills dir: %w", err)
}
for _, entry := range entries {
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".md") {
continue
}
path := filepath.Join(dir, entry.Name())
data, err := os.ReadFile(path)
if err != nil {
continue
}
skill, err := parseFrontmatter(string(data))
if err != nil {
continue
}
skill.Path = path
if skill.Name == "" {
skill.Name = strings.TrimSuffix(entry.Name(), ".md")
}
m.skills = append(m.skills, skill)
}
return nil
}
func (m *Manager) All() []*Skill {
return m.skills
}
func (m *Manager) Activate(name string) error {
for _, s := range m.skills {
if s.Name == name {
s.Active = true
return nil
}
}
return fmt.Errorf("skill not found: %s", name)
}
func (m *Manager) Deactivate(name string) error {
for _, s := range m.skills {
if s.Name == name {
s.Active = false
return nil
}
}
return fmt.Errorf("skill not found: %s", name)
}
func (m *Manager) ActiveContent() string {
var parts []string
for _, s := range m.skills {
if s.Active && s.Content != "" {
parts = append(parts, fmt.Sprintf("### %s\n%s", s.Name, s.Content))
}
}
return strings.Join(parts, "\n\n")
}