package ingest import ( "fmt" "os" "path/filepath" "strings" ) var _ Ingester = (*SkillsIngester)(nil) type SkillsIngester struct { Version string } func NewSkillsIngester() *SkillsIngester { return &SkillsIngester{Version: "skills-index/v1"} } func (s *SkillsIngester) SourceID() string { return "skills-catalog" } func (s *SkillsIngester) Ingest(path string) (*IngestResult, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("read skill: %w", err) } if len(data) < 20 { return nil, nil } content := string(data) title := extractSkillName(content, path) summary := extractSkillSummary(content) tags := extractSkillTags(content) projects := extractProjects(tags) createdAt := extractCreatedAt(content) fp := FingerprintWithMeta(data, map[string]string{ "source": "skills-catalog", "title": title, }) return &IngestResult{ Fingerprint: fp, SourceID: s.SourceID(), SourcePath: path, Project: projects, ContentType: ".md", Title: title, Summary: summary, CreatedAt: createdAt, LineStart: 0, LineEnd: len(strings.Split(content, "\n")), Confidence: 0.9, IngesterVersion: s.Version, Provenance: map[string]any{ "skill_name": title, "tags": tags, "line_count": len(strings.Split(content, "\n")), }, }, nil } func extractSkillName(content, path string) string { base := filepath.Base(filepath.Dir(path)) if base != "" && base != "." && base != "/" { return base } return strings.TrimSuffix(filepath.Base(path), ".md") } func extractSkillSummary(content string) string { for _, line := range strings.Split(content, "\n") { trimmed := strings.TrimSpace(line) if strings.HasPrefix(trimmed, "description:") { desc := strings.TrimSpace(trimmed[len("description:"):]) if len(desc) > 200 { desc = desc[:200] + "..." } return desc } } for _, line := range strings.Split(content, "\n") { trimmed := strings.TrimSpace(line) if strings.HasPrefix(trimmed, "# ") { continue } if trimmed != "" && !strings.HasPrefix(trimmed, "---") { return truncate(trimmed, 200) } } return "" } func extractSkillTags(content string) []string { for _, line := range strings.Split(content, "\n") { trimmed := strings.TrimSpace(line) if strings.HasPrefix(trimmed, "tags:") { raw := strings.TrimSpace(trimmed[len("tags:"):]) raw = strings.Trim(raw, "\"[]") var tags []string for _, t := range strings.Split(raw, ",") { t = strings.TrimSpace(t) t = strings.Trim(t, "\" ") if t != "" { tags = append(tags, t) } } return tags } } return nil } func extractProjects(tags []string) string { for _, t := range tags { if strings.HasPrefix(t, "scope:project:") { return strings.TrimPrefix(t, "scope:project:") } if strings.HasPrefix(t, "scope:machine:") { return "[machine]" } } return "" } func extractCreatedAt(content string) string { for _, line := range strings.Split(content, "\n") { trimmed := strings.TrimSpace(line) if strings.HasPrefix(trimmed, "created_at:") || strings.HasPrefix(trimmed, "updated_at:") { return strings.TrimSpace(trimmed[strings.Index(trimmed, ":")+1:]) } } return "" }