Skip to main content

mars_agents/
local_source.rs

1use std::path::{Path, PathBuf};
2
3use crate::discover::{self, DiscoveredItem};
4use crate::error::MarsError;
5
6pub const LOCAL_SOURCE_DIR: &str = ".mars-src";
7
8#[derive(Debug, Clone)]
9pub struct LocalDiscoveredItem {
10    pub discovered: DiscoveredItem,
11    pub root: PathBuf,
12}
13
14impl LocalDiscoveredItem {
15    pub fn disk_path(&self) -> PathBuf {
16        self.root.join(&self.discovered.source_path)
17    }
18}
19
20pub fn preferred_local_source_root(project_root: &Path) -> PathBuf {
21    project_root.join(LOCAL_SOURCE_DIR)
22}
23
24pub fn local_discovery_roots(project_root: &Path) -> Vec<PathBuf> {
25    vec![preferred_local_source_root(project_root)]
26}
27
28pub fn discover_local_items(
29    project_root: &Path,
30    source_name: Option<&str>,
31) -> Result<Vec<LocalDiscoveredItem>, MarsError> {
32    let mut merged = Vec::new();
33
34    for root in local_discovery_roots(project_root) {
35        let discovered = discover::discover_source(&root, source_name)?;
36        for item in discovered {
37            merged.push(LocalDiscoveredItem {
38                discovered: item,
39                root: root.clone(),
40            });
41        }
42    }
43
44    Ok(merged)
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50    use crate::types::ItemKind;
51    use tempfile::TempDir;
52
53    #[test]
54    fn discovers_mars_src_not_repo_root() {
55        let dir = TempDir::new().unwrap();
56        let project_root = dir.path();
57
58        std::fs::create_dir_all(project_root.join("skills").join("planning")).unwrap();
59        std::fs::write(
60            project_root
61                .join("skills")
62                .join("planning")
63                .join("SKILL.md"),
64            "# Legacy",
65        )
66        .unwrap();
67
68        let preferred = preferred_local_source_root(project_root)
69            .join("skills")
70            .join("planning");
71        std::fs::create_dir_all(&preferred).unwrap();
72        std::fs::write(preferred.join("SKILL.md"), "# Preferred").unwrap();
73
74        let items = discover_local_items(project_root, Some("_self")).unwrap();
75
76        assert_eq!(items.len(), 1);
77        assert_eq!(items[0].discovered.id.kind, ItemKind::Skill);
78        assert_eq!(items[0].discovered.id.name.as_str(), "planning");
79        assert_eq!(items[0].root, preferred_local_source_root(project_root));
80    }
81}