llama_cpp_v3_agent_sdk/
agents_md.rs1use std::path::{Path, PathBuf};
11
12#[derive(Debug, Clone)]
14pub struct AgentsMdFile {
15 pub path: PathBuf,
17 pub content: String,
19}
20
21pub struct AgentsMdRegistry {
23 files: Vec<AgentsMdFile>,
24}
25
26impl AgentsMdRegistry {
27 pub fn new() -> Self {
28 Self { files: Vec::new() }
29 }
30
31 pub fn discover(&mut self) {
33 self.files.clear();
34
35 if let Ok(cwd) = std::env::current_dir() {
37 let git_root = find_git_root(&cwd);
38 let stop_at = git_root.as_deref();
39
40 let mut dir = Some(cwd.as_path());
41 while let Some(current) = dir {
42 let agents_path = current.join("AGENTS.md");
43 if agents_path.is_file() {
44 if let Ok(content) = std::fs::read_to_string(&agents_path) {
45 self.files.push(AgentsMdFile {
46 path: agents_path,
47 content,
48 });
49 }
50 }
51
52 if let Some(root) = stop_at {
54 if current == root {
55 break;
56 }
57 }
58
59 dir = current.parent();
60 }
61 }
62
63 if let Some(home) = dirs::home_dir() {
65 let global_path = home.join(".llama-agent").join("AGENTS.md");
66 if global_path.is_file() {
67 if !self.files.iter().any(|f| f.path == global_path) {
69 if let Ok(content) = std::fs::read_to_string(&global_path) {
70 self.files.push(AgentsMdFile {
71 path: global_path,
72 content,
73 });
74 }
75 }
76 }
77 }
78 }
79
80 pub fn files(&self) -> &[AgentsMdFile] {
82 &self.files
83 }
84
85 pub fn agents_md_prompt(&self) -> String {
89 if self.files.is_empty() {
90 return String::new();
91 }
92
93 let mut lines = Vec::new();
94 lines.push("# Project Guidelines (from AGENTS.md)\n".to_string());
95
96 for file in &self.files {
97 let path_display = file.path.display().to_string();
98 lines.push(format!("<!-- Source: {} -->\n", path_display));
99 lines.push(file.content.clone());
100 lines.push(String::new());
101 }
102
103 lines.join("\n")
104 }
105
106 pub fn len(&self) -> usize {
108 self.files.len()
109 }
110
111 pub fn is_empty(&self) -> bool {
112 self.files.is_empty()
113 }
114}
115
116impl Default for AgentsMdRegistry {
117 fn default() -> Self {
118 Self::new()
119 }
120}
121
122fn find_git_root(start: &Path) -> Option<PathBuf> {
124 let mut dir = Some(start);
125 while let Some(current) = dir {
126 if current.join(".git").exists() {
127 return Some(current.to_path_buf());
128 }
129 dir = current.parent();
130 }
131 None
132}