DiscoverSkillsWithOptions finds all skills in a repository at the given commit SHA, with configurable discovery behavior.
(client *api.Client, host, owner, repo, commitSHA string, opts DiscoverOptions)
| 574 | // DiscoverSkillsWithOptions finds all skills in a repository at the given |
| 575 | // commit SHA, with configurable discovery behavior. |
| 576 | func DiscoverSkillsWithOptions(client *api.Client, host, owner, repo, commitSHA string, opts DiscoverOptions) ([]Skill, error) { |
| 577 | apiPath, err := safeurl.JoinPath("repos", owner, repo, "git", "trees", commitSHA) |
| 578 | if err != nil { |
| 579 | return nil, err |
| 580 | } |
| 581 | apiPath.SetQuery("recursive", "true") |
| 582 | var tree treeResponse |
| 583 | if err := client.REST(host, "GET", apiPath.String(), nil, &tree); err != nil { |
| 584 | return nil, fmt.Errorf("could not fetch repository tree: %w", err) |
| 585 | } |
| 586 | |
| 587 | if tree.Truncated { |
| 588 | return nil, &TreeTooLargeError{Owner: owner, Repo: repo} |
| 589 | } |
| 590 | |
| 591 | treeSHAs := make(map[string]string) |
| 592 | for _, entry := range tree.Tree { |
| 593 | if entry.Type == "tree" { |
| 594 | treeSHAs[entry.Path] = entry.SHA |
| 595 | } |
| 596 | } |
| 597 | |
| 598 | seen := make(map[string]bool) |
| 599 | var matches []skillMatch |
| 600 | for _, entry := range tree.Tree { |
| 601 | if entry.Type != "blob" { |
| 602 | continue |
| 603 | } |
| 604 | m := matchSkillConventions(entry) |
| 605 | if m == nil { |
| 606 | m = matchHiddenDirConventions(entry) |
| 607 | } |
| 608 | if m == nil { |
| 609 | continue |
| 610 | } |
| 611 | if seen[m.skillDir] { |
| 612 | continue |
| 613 | } |
| 614 | seen[m.skillDir] = true |
| 615 | matches = append(matches, *m) |
| 616 | } |
| 617 | |
| 618 | if len(matches) == 0 { |
| 619 | return nil, fmt.Errorf( |
| 620 | "no skills found in %s/%s\n"+ |
| 621 | " Expected skills in skills/*/SKILL.md, skills/{scope}/*/SKILL.md,\n"+ |
| 622 | " {prefix}/skills/*/SKILL.md, {prefix}/skills/{scope}/*/SKILL.md,\n"+ |
| 623 | " */SKILL.md, or plugins/*/skills/*/SKILL.md\n"+ |
| 624 | " This repository may be a curated list rather than a skills publisher", |
| 625 | owner, repo, |
| 626 | ) |
| 627 | } |
| 628 | |
| 629 | var skills []Skill |
| 630 | for _, m := range matches { |
| 631 | skills = append(skills, Skill{ |
| 632 | Name: m.name, |
| 633 | Namespace: m.namespace, |