agent_exec/
install_skills.rs1use anyhow::Result;
7
8use crate::schema::{InstallSkillsData, InstalledSkillSummary, Response};
9use crate::skills::{LockEntry, LockFile, Source, install, now_rfc3339, resolve_agents_dir};
10
11pub struct InstallSkillsOpts<'a> {
13 pub source: &'a str,
15 pub global: bool,
17}
18
19pub fn execute(opts: InstallSkillsOpts<'_>) -> Result<()> {
24 let source = Source::parse(opts.source)?;
26
27 let agents_dir = resolve_agents_dir(opts.global)?;
29
30 let installed = install(&source, &agents_dir)?;
32
33 let lock_path = agents_dir.join(".skill-lock.json");
35 let mut lock = LockFile::read(&lock_path)?;
36 let entry = LockEntry {
37 name: installed.name.clone(),
38 source_type: installed.source_str.clone(),
39 installed_at: now_rfc3339(),
40 path: installed.path.to_string_lossy().into_owned(),
41 };
42 lock.upsert(entry);
43 lock.write(&lock_path)?;
44
45 let data = InstallSkillsData {
47 skills: vec![InstalledSkillSummary {
48 name: installed.name,
49 source_type: installed.source_str,
50 path: installed.path.to_string_lossy().into_owned(),
51 }],
52 global: opts.global,
53 lock_file_path: lock_path.to_string_lossy().into_owned(),
54 };
55 Response::new("install_skills", data).print();
56 Ok(())
57}