Install fetches and writes skills to the target directory.
(opts *Options)
| 54 | |
| 55 | // Install fetches and writes skills to the target directory. |
| 56 | func Install(opts *Options) (*Result, error) { |
| 57 | targetDir := opts.Dir |
| 58 | if targetDir == "" { |
| 59 | if opts.AgentHost == nil { |
| 60 | return nil, fmt.Errorf("either Dir or AgentHost must be specified") |
| 61 | } |
| 62 | var err error |
| 63 | targetDir, err = opts.AgentHost.InstallDir(opts.Scope, opts.GitRoot, opts.HomeDir) |
| 64 | if err != nil { |
| 65 | return nil, err |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | if len(opts.Skills) == 1 { |
| 70 | skill := opts.Skills[0] |
| 71 | if opts.OnProgress != nil { |
| 72 | opts.OnProgress(0, 1) |
| 73 | defer opts.OnProgress(1, 1) |
| 74 | } |
| 75 | if err := installSkill(opts, skill, targetDir); err != nil { |
| 76 | return nil, fmt.Errorf("failed to install skill %q: %w", skill.InstallName(), err) |
| 77 | } |
| 78 | var warnings []string |
| 79 | if err := lockfile.RecordInstall(opts.Host, skill.InstallName(), opts.Owner, opts.Repo, skill.Path+"/SKILL.md", skill.TreeSHA, opts.PinnedRef); err != nil { |
| 80 | warnings = append(warnings, fmt.Sprintf("could not record install for %s: %v", skill.InstallName(), err)) |
| 81 | } |
| 82 | return &Result{Installed: []string{skill.InstallName()}, Dir: targetDir, Warnings: warnings}, nil |
| 83 | } |
| 84 | |
| 85 | total := len(opts.Skills) |
| 86 | if opts.OnProgress != nil { |
| 87 | opts.OnProgress(0, total) |
| 88 | } |
| 89 | |
| 90 | type job struct { |
| 91 | idx int |
| 92 | skill discovery.Skill |
| 93 | } |
| 94 | jobs := make(chan job) |
| 95 | |
| 96 | results := make([]skillResult, total) |
| 97 | var wg sync.WaitGroup |
| 98 | var done atomic.Int32 |
| 99 | |
| 100 | workers := min(maxConcurrency, total) |
| 101 | for range workers { |
| 102 | wg.Go(func() { |
| 103 | for j := range jobs { |
| 104 | err := installSkill(opts, j.skill, targetDir) |
| 105 | results[j.idx] = skillResult{name: j.skill.InstallName(), err: err} |
| 106 | |
| 107 | if opts.OnProgress != nil { |
| 108 | opts.OnProgress(int(done.Add(1)), total) |
| 109 | } |
| 110 | } |
| 111 | }) |
| 112 | } |
| 113 |