1use std::fs;
2use std::io;
3use std::path::Path;
4
5use skillflag::{Options, handle_skillflag};
6
7const SKILL_ID: &str = "yarp";
8const SKILL_MD: &str = include_str!("../skills/yarp/SKILL.md");
9
10#[must_use]
14pub fn maybe_run(arguments: &[String]) -> Option<i32> {
15 if arguments.get(1).map(String::as_str) != Some("--skill") {
16 return None;
17 }
18 Some(match materialize_and_run(arguments) {
19 Ok(code) => code,
20 Err(error) => {
21 eprintln!("yarp: could not prepare bundled skill: {error}");
22 1
23 }
24 })
25}
26
27fn materialize_and_run(arguments: &[String]) -> io::Result<i32> {
28 let temporary = tempfile::Builder::new().prefix("yarp-skill-").tempdir()?;
29 let bundle_root = temporary.path().join("skills");
30 let yarp_dir = bundle_root.join(SKILL_ID);
31 fs::create_dir_all(&yarp_dir)?;
32 let skill_path = yarp_dir.join("SKILL.md");
33 fs::write(&skill_path, SKILL_MD)?;
34 set_export_permissions(&bundle_root, &yarp_dir, &skill_path)?;
35
36 let options = Options {
37 skills_roots: vec![bundle_root],
38 include_bundled_skill: false,
39 ..Options::default()
40 };
41 Ok(handle_skillflag(arguments, &options))
42}
43
44#[cfg(unix)]
45fn set_export_permissions(
46 bundle_root: &Path,
47 yarp_dir: &Path,
48 skill_path: &Path,
49) -> io::Result<()> {
50 use std::os::unix::fs::PermissionsExt as _;
51
52 fs::set_permissions(bundle_root, fs::Permissions::from_mode(0o755))?;
53 fs::set_permissions(yarp_dir, fs::Permissions::from_mode(0o755))?;
54 fs::set_permissions(skill_path, fs::Permissions::from_mode(0o644))
55}
56
57#[cfg(not(unix))]
58fn set_export_permissions(
59 _bundle_root: &Path,
60 _yarp_dir: &Path,
61 _skill_path: &Path,
62) -> io::Result<()> {
63 Ok(())
64}