codetether_agent/agent/
builtin.rs1use super::{AgentInfo, AgentMode};
4use std::path::Path;
5
6pub fn build_agent() -> AgentInfo {
8 AgentInfo {
9 name: "build".to_string(),
10 description: Some("Full access agent for development work".to_string()),
11 mode: AgentMode::Primary,
12 native: true,
13 hidden: false,
14 model: None,
15 temperature: None,
16 top_p: None,
17 max_steps: Some(100),
18 }
19}
20
21pub fn plan_agent() -> AgentInfo {
23 AgentInfo {
24 name: "plan".to_string(),
25 description: Some("Read-only agent for analysis and code exploration".to_string()),
26 mode: AgentMode::Primary,
27 native: true,
28 hidden: false,
29 model: None,
30 temperature: None,
31 top_p: None,
32 max_steps: Some(50),
33 }
34}
35
36pub fn explore_agent() -> AgentInfo {
38 AgentInfo {
39 name: "explore".to_string(),
40 description: Some("Fast agent for exploring codebases".to_string()),
41 mode: AgentMode::Subagent,
42 native: true,
43 hidden: false,
44 model: None,
45 temperature: None,
46 top_p: None,
47 max_steps: Some(20),
48 }
49}
50
51#[allow(dead_code)]
53pub const BUILD_SYSTEM_PROMPT: &str = r#"You are an expert AI programming assistant called CodeTether Agent.
54
55You help users with software development tasks including:
56- Writing and editing code
57- Debugging and fixing issues
58- Implementing new features
59- Refactoring and improving code quality
60- Explaining code and concepts
61
62You have access to tools that let you:
63- Read and write files
64- Run shell commands
65- Search the codebase
66- List directories
67
68Always:
69- Be concise and helpful
70- Show your work by using tools
71- Explain what you're doing
72- Ask clarifying questions when needed
73- Follow best practices for the language/framework being used
74
75Current working directory: {cwd}
76"#;
77
78#[allow(dead_code)]
80pub const PLAN_SYSTEM_PROMPT: &str = r#"You are an expert AI assistant for code analysis and planning.
81
82Your role is to:
83- Explore and understand codebases
84- Analyze code structure and architecture
85- Plan changes and refactoring
86- Answer questions about the code
87
88You have read-only access to the codebase. You can:
89- Read files
90- Search the codebase
91- List directories
92- Run safe commands
93
94You should NOT modify any files. If the user wants changes, explain what should be changed and suggest switching to the build agent.
95
96Current working directory: {cwd}
97"#;
98
99#[allow(dead_code)]
104pub const EXPLORE_SYSTEM_PROMPT: &str = r#"You are a fast, focused agent for codebase exploration.
105
106Your job is to quickly find relevant code and information. Use tools efficiently:
107- Use glob to find files by pattern
108- Use grep to search for text
109- Use list to see directory contents
110- Read files to get details
111
112Be thorough but fast. Return the most relevant results without unnecessary exploration.
113"#;
114
115pub fn load_agents_md(start_dir: &Path) -> Option<(String, std::path::PathBuf)> {
118 let mut current = start_dir.to_path_buf();
119
120 loop {
121 let agents_path = current.join("AGENTS.md");
122 if agents_path.exists() {
123 if let Ok(content) = std::fs::read_to_string(&agents_path) {
124 return Some((content, agents_path));
125 }
126 }
127
128 if !current.pop() {
130 break;
131 }
132 }
133
134 None
135}
136
137pub fn load_all_agents_md(start_dir: &Path) -> Vec<(String, std::path::PathBuf)> {
140 let mut results = Vec::new();
141 let mut current = start_dir.to_path_buf();
142
143 loop {
144 let agents_path = current.join("AGENTS.md");
145 if agents_path.exists() {
146 if let Ok(content) = std::fs::read_to_string(&agents_path) {
147 results.push((content, agents_path));
148 }
149 }
150
151 if !current.pop() {
153 break;
154 }
155 }
156
157 results
158}
159
160pub fn build_system_prompt(cwd: &Path) -> String {
162 let base_prompt = BUILD_SYSTEM_PROMPT.replace("{cwd}", &cwd.display().to_string());
163
164 let agents_files = load_all_agents_md(cwd);
166
167 if agents_files.is_empty() {
168 return base_prompt;
169 }
170
171 let mut agents_section = String::new();
173 agents_section.push_str("\n\n## Project Instructions (AGENTS.md)\n\n");
174 agents_section
175 .push_str("The following instructions were loaded from AGENTS.md files in the project.\n");
176 agents_section
177 .push_str("Follow these project-specific guidelines when working on this codebase.\n\n");
178
179 for (content, path) in agents_files.iter().rev() {
181 agents_section.push_str(&format!("### From {}\n\n", path.display()));
182 agents_section.push_str(content);
183 agents_section.push_str("\n\n");
184 }
185
186 format!("{base_prompt}{agents_section}")
187}
188
189#[allow(dead_code)]
191pub fn build_plan_system_prompt(cwd: &Path) -> String {
192 let base_prompt = PLAN_SYSTEM_PROMPT.replace("{cwd}", &cwd.display().to_string());
193
194 let agents_files = load_all_agents_md(cwd);
196
197 if agents_files.is_empty() {
198 return base_prompt;
199 }
200
201 let mut agents_section = String::new();
202 agents_section.push_str("\n\n## Project Instructions (AGENTS.md)\n\n");
203
204 for (content, path) in agents_files.iter().rev() {
205 agents_section.push_str(&format!("### From {}\n\n", path.display()));
206 agents_section.push_str(content);
207 agents_section.push_str("\n\n");
208 }
209
210 format!("{base_prompt}{agents_section}")
211}