mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-04-21 18:26:38 +02:00
156 lines
3.8 KiB
Go
156 lines
3.8 KiB
Go
package skillpackage
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// ListSkillSummaries scans skillsRoot and returns index rows for the admin API.
|
|
func ListSkillSummaries(skillsRoot string) ([]SkillSummary, error) {
|
|
names, err := ListSkillDirNames(skillsRoot)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sort.Strings(names)
|
|
out := make([]SkillSummary, 0, len(names))
|
|
for _, dirName := range names {
|
|
su, err := loadSummary(skillsRoot, dirName)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
out = append(out, su)
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func loadSummary(skillsRoot, dirName string) (SkillSummary, error) {
|
|
skillPath := SkillDir(skillsRoot, dirName)
|
|
mdPath, err := ResolveSKILLPath(skillPath)
|
|
if err != nil {
|
|
return SkillSummary{}, err
|
|
}
|
|
raw, err := os.ReadFile(mdPath)
|
|
if err != nil {
|
|
return SkillSummary{}, err
|
|
}
|
|
man, _, err := ParseSkillMD(raw)
|
|
if err != nil {
|
|
return SkillSummary{}, err
|
|
}
|
|
if err := ValidateAgentSkillManifestInPackage(man, dirName); err != nil {
|
|
return SkillSummary{}, err
|
|
}
|
|
fi, err := os.Stat(mdPath)
|
|
if err != nil {
|
|
return SkillSummary{}, err
|
|
}
|
|
pfiles, err := ListPackageFiles(skillsRoot, dirName)
|
|
if err != nil {
|
|
return SkillSummary{}, err
|
|
}
|
|
nFiles := 0
|
|
for _, p := range pfiles {
|
|
if !p.IsDir {
|
|
nFiles++
|
|
}
|
|
}
|
|
scripts, err := listScripts(skillsRoot, dirName)
|
|
if err != nil {
|
|
return SkillSummary{}, err
|
|
}
|
|
ver := versionFromMetadata(man)
|
|
return SkillSummary{
|
|
ID: dirName,
|
|
DirName: dirName,
|
|
Name: man.Name,
|
|
Description: man.Description,
|
|
Version: ver,
|
|
Path: skillPath,
|
|
Tags: manifestTags(man),
|
|
ScriptCount: len(scripts),
|
|
FileCount: nFiles,
|
|
FileSize: fi.Size(),
|
|
ModTime: fi.ModTime().Format("2006-01-02 15:04:05"),
|
|
Progressive: true,
|
|
}, nil
|
|
}
|
|
|
|
// LoadOptions mirrors legacy API query params for the web admin.
|
|
type LoadOptions struct {
|
|
Depth string // summary | full
|
|
Section string
|
|
}
|
|
|
|
// LoadSkill returns manifest + body + package listing for admin.
|
|
func LoadSkill(skillsRoot, skillID string, opt LoadOptions) (*SkillView, error) {
|
|
skillPath := SkillDir(skillsRoot, skillID)
|
|
mdPath, err := ResolveSKILLPath(skillPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
raw, err := os.ReadFile(mdPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
man, body, err := ParseSkillMD(raw)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := ValidateAgentSkillManifestInPackage(man, skillID); err != nil {
|
|
return nil, err
|
|
}
|
|
pfiles, err := ListPackageFiles(skillsRoot, skillID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
scripts, err := listScripts(skillsRoot, skillID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sort.Slice(scripts, func(i, j int) bool { return scripts[i].RelPath < scripts[j].RelPath })
|
|
sections := deriveSections(body)
|
|
ver := versionFromMetadata(man)
|
|
v := &SkillView{
|
|
DirName: skillID,
|
|
Name: man.Name,
|
|
Description: man.Description,
|
|
Content: body,
|
|
Path: skillPath,
|
|
Version: ver,
|
|
Tags: manifestTags(man),
|
|
Scripts: scripts,
|
|
Sections: sections,
|
|
PackageFiles: pfiles,
|
|
}
|
|
depth := strings.ToLower(strings.TrimSpace(opt.Depth))
|
|
if depth == "" {
|
|
depth = "full"
|
|
}
|
|
sec := strings.TrimSpace(opt.Section)
|
|
if sec != "" {
|
|
mds := splitMarkdownSections(body)
|
|
chunk := findSectionContent(mds, sec)
|
|
if chunk == "" {
|
|
v.Content = fmt.Sprintf("_(section %q not found in SKILL.md for skill %s)_", sec, skillID)
|
|
} else {
|
|
v.Content = chunk
|
|
}
|
|
return v, nil
|
|
}
|
|
if depth == "summary" {
|
|
v.Content = buildSummaryMarkdown(man.Name, man.Description, v.Tags, scripts, sections, body)
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
// ReadScriptText returns file content as string (for HTTP resource_path).
|
|
func ReadScriptText(skillsRoot, skillID, relPath string, maxBytes int64) (string, error) {
|
|
b, err := ReadPackageFile(skillsRoot, skillID, relPath, maxBytes)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(b), nil
|
|
}
|