use include_dir::{Dir, DirEntry, include_dir};
use std::fs;
use std::path::{Path, PathBuf};
static EMBEDDED_DEFAULT_SKILLS: Dir<'static> =
include_dir!("$CARGO_MANIFEST_DIR/share/default-skills");
pub fn resolve_share_dir(workspace: &Path) -> PathBuf {
let dev = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("share");
if dev.join("default-skills").is_dir() {
return dev;
}
let cache_root = workspace.join("share");
let target = cache_root.join("default-skills");
if let Err(e) = extract_dir(&EMBEDDED_DEFAULT_SKILLS, &target) {
tracing::warn!(error = %e, target = %target.display(), "failed to extract embedded default skills");
}
cache_root
}
fn extract_dir(dir: &Dir<'_>, target: &Path) -> std::io::Result<()> {
for entry in dir.entries() {
let path = target.join(entry.path());
match entry {
DirEntry::Dir(d) => {
fs::create_dir_all(&path)?;
extract_dir(d, target)?;
}
DirEntry::File(f) => {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
fs::write(&path, f.contents())?;
}
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn embedded_tree_contains_skill_creator() {
let mut found = false;
for entry in EMBEDDED_DEFAULT_SKILLS.entries() {
if entry.path().to_string_lossy() == "skill-creator" {
found = true;
}
}
assert!(found, "embedded default-skills must contain skill-creator/");
}
#[test]
fn extract_dir_round_trips() {
let tmp = tempfile::tempdir().unwrap();
let out = tmp.path().join("extracted");
extract_dir(&EMBEDDED_DEFAULT_SKILLS, &out).unwrap();
assert!(out.join("skill-creator/SKILL.md").exists());
assert!(out.join("skill-creator/references/schemas.md").exists());
assert!(out.join("skill-creator/agents/grader.md").exists());
}
#[test]
fn resolve_prefers_dev_path_when_present() {
let dev = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("share");
let resolved = resolve_share_dir(Path::new("/nonexistent/workspace"));
assert_eq!(resolved, dev);
}
}