a_agent/context/
agents.rs1use std::collections::BTreeMap;
2use std::fs;
3use std::path::{Path, PathBuf};
4
5use anyhow::{Context, Result};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct AgentsFile {
9 pub path: PathBuf,
10 pub content: String,
11}
12
13pub fn discover_agents(cwd: &Path, global: Option<&Path>) -> Result<Vec<AgentsFile>> {
14 let mut files = Vec::new();
15 if let Some(path) = global.filter(|path| path.is_file()) {
16 files.push(read_agents(path)?);
17 }
18
19 let boundary = repository_boundary(cwd);
20 let mut candidates = Vec::new();
21 let mut current = Some(cwd);
22 while let Some(path) = current {
23 candidates.push(path.join("AGENTS.md"));
24 if path == boundary {
25 break;
26 }
27 current = path.parent();
28 }
29 candidates.reverse();
30 for path in candidates.into_iter().filter(|path| path.is_file()) {
31 files.push(read_agents(&path)?);
32 }
33 Ok(files)
34}
35
36pub fn discover_agents_for_targets(
37 cwd: &Path,
38 global: Option<&Path>,
39 targets: &[PathBuf],
40) -> Result<Vec<AgentsFile>> {
41 let global_path = global.map(Path::to_path_buf);
42 let mut unique = BTreeMap::new();
43 for item in discover_agents(cwd, global)? {
44 unique.insert(item.path.clone(), item);
45 }
46 for target in targets {
47 let directory = if target.is_dir() {
48 target.as_path()
49 } else {
50 target.parent().unwrap_or(cwd)
51 };
52 for item in discover_agents(directory, None)? {
53 unique.insert(item.path.clone(), item);
54 }
55 }
56 let mut files = unique.into_values().collect::<Vec<_>>();
57 files.sort_by_key(|item| {
58 (
59 usize::from(global_path.as_ref() != Some(&item.path)),
60 item.path.components().count(),
61 item.path.clone(),
62 )
63 });
64 Ok(files)
65}
66
67fn repository_boundary(cwd: &Path) -> &Path {
68 cwd.ancestors()
69 .find(|path| path.join(".git").exists())
70 .unwrap_or(cwd)
71}
72
73fn read_agents(path: &Path) -> Result<AgentsFile> {
74 Ok(AgentsFile {
75 path: path.to_path_buf(),
76 content: fs::read_to_string(path)
77 .with_context(|| format!("read AGENTS.md {}", path.display()))?,
78 })
79}