(resolved *ResolvedWorkflow)
| 765 | } |
| 766 | |
| 767 | func resolveSkillRelativePath(resolved *ResolvedWorkflow) (string, error) { |
| 768 | // Determine the relative path under the skill directory so nested files preserve |
| 769 | // structure (e.g. "scripts/query.sh"). Match a skill-name path component that is |
| 770 | // immediately under skills/ or .github/skills/ to avoid accidental first matches. |
| 771 | parts := strings.Split(filepath.ToSlash(resolved.Spec.WorkflowPath), "/") |
| 772 | var relParts []string |
| 773 | for i, part := range parts { |
| 774 | if i >= len(parts)-1 { |
| 775 | break |
| 776 | } |
| 777 | if part != resolved.SkillName { |
| 778 | continue |
| 779 | } |
| 780 | if i > 0 && parts[i-1] == "skills" { |
| 781 | relParts = parts[i+1:] |
| 782 | break |
| 783 | } |
| 784 | if i > 1 && parts[i-1] == "skills" && parts[i-2] == ".github" { |
| 785 | relParts = parts[i+1:] |
| 786 | break |
| 787 | } |
| 788 | } |
| 789 | if len(relParts) == 0 { |
| 790 | return "", fmt.Errorf("failed to determine relative path for skill %q from source path %q", resolved.SkillName, resolved.Spec.WorkflowPath) |
| 791 | } |
| 792 | relPath := filepath.Clean(filepath.Join(relParts...)) |
| 793 | if relPath == "." || relPath == "" || relPath == string(os.PathSeparator) { |
| 794 | return "", fmt.Errorf("invalid relative skill path %q from source path %q", relPath, resolved.Spec.WorkflowPath) |
| 795 | } |
| 796 | return relPath, nil |
| 797 | } |
| 798 | |
| 799 | // addAgentFileWithTracking installs a single agent file from a package to the agentic engine |
| 800 | // agents directory. |
no test coverage detected