mars_agents/
local_source.rs1use 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}