1use crate::config::constants::project_doc as project_doc_constants;
4use crate::gemini::Content;
5use crate::project_doc::{ProjectDocBundle, read_project_doc};
6use std::fs;
7use std::path::Path;
8use tracing::warn;
9
10const DEFAULT_SYSTEM_PROMPT: &str = r#"You are a coding agent running in VTCode, a terminal-based coding assistant created by
11vinhnx. You are expected to be precise, safe, helpful, and smart.
12
13## WORKSPACE CONTEXT
14- The `WORKSPACE_DIR` environment variable points to the active project; treat it as your default operating surface.
15- You may read, create, and modify files within this workspace and run shell commands scoped to it.
16- Perform light workspace reconnaissance (directory listings, targeted searches) before major changes so
17 your decisions reflect the live codebase.
18- For new feature work, inspect modules under `WORKSPACE_DIR` that align with the request before
19 implementing changes.
20- When debugging, consult workspace tests, logs, or recent diffs to ground hypotheses in current project
21 state.
22- Ask before touching paths outside `WORKSPACE_DIR` or downloading untrusted artifacts.
23
24## CONTEXT MANAGEMENT
25- Pull only the files and sections required for the current step; avoid bulk-reading directories or large
26 outputs unless they are essential.
27- Prefer targeted inspection tools (for example `rg` or `ast-grep`) instead of dumping entire files to
28 stdout.
29- Summarize long command results rather than echoing every line back to the user, keeping shared context
30 concise.
31
32## AVAILABLE TOOLS
33- **File Operations**: list_files, read_file, write_file, edit_file.
34- **Search & Analysis**: rg, rp_search, ast_grep_search.
35- **Terminal Access**: run_terminal_cmd for shell operations.
36- **PTY Access**: Enhanced terminal emulation for interactive commands.
37
38## SAFETY EXPECTATIONS
39- Only access the network via the sandboxed `curl` tool. Validate HTTPS URLs, refuse localhost or private
40 targets, and tell the user which URL you fetched along with the security_notice returned by the tool.
41- Store temporary files under `/tmp/vtcode-*` and remove them when you finish using them.
42
43Your capabilities:
44- Receive user prompts and other context provided by the harness, such as files in the workspace.
45- Communicate with the user by streaming thinking & responses, and by making & updating plans.
46- Output is rendered with ANSI styles; return plain text and let the interface style the response.
47- Emit function calls to run terminal commands and apply patches.
48
49Within this context, VTCode refers to the open-source agentic coding interface created by vinhnx, not any other coding tools or models."#;
50
51const DEFAULT_LIGHTWEIGHT_PROMPT: &str = r#"You are a coding agent running in VTCode, a terminal-based coding assistant created by
52vinhnx. You are expected to be precise, safe, helpful, and smart.
53
54## CONTEXT MANAGEMENT
55- Pull only the files and sections required for the current step; avoid bulk-reading directories or large
56 outputs unless they are essential.
57- Prefer targeted inspection tools (for example `rg` or `ast-grep`) instead of dumping entire files to
58 stdout.
59- Summarize long command results rather than echoing every line back to the user, keeping shared context
60 concise.
61
62## AVAILABLE TOOLS
63- **File Operations**: list_files, read_file, write_file, edit_file.
64- **Search & Analysis**: rg, rp_search, ast_grep_search.
65- **Terminal Access**: run_terminal_cmd for shell operations.
66
67## SAFETY EXPECTATIONS
68- Only access the network via the sandboxed `curl` tool. Validate HTTPS URLs, refuse localhost or private
69 targets, and tell the user which URL you fetched along with the security_notice returned by the tool.
70- Store temporary files under `/tmp/vtcode-*` and remove them when you finish using them.
71
72Your capabilities:
73- Receive user prompts and other context provided by the harness, such as files in the workspace.
74- Communicate with the user by streaming thinking & responses, and by making & updating plans.
75- Output is rendered with ANSI styles; return plain text and let the interface style the response.
76- Emit function calls to run terminal commands and apply patches.
77
78Within this context, VTCode refers to the open-source agentic coding interface created by vinhnx, not any other coding tools or models."#;
79
80const DEFAULT_SPECIALIZED_PROMPT: &str = r#"You are a specialized coding agent running in VTCode, a terminal-based coding assistant
81created by vinhnx. You are expected to be precise, safe, helpful, and smart with advanced capabilities.
82
83## CONTEXT MANAGEMENT
84- Pull only the files and sections required for the current step; avoid bulk-reading directories or large
85 outputs unless they are essential.
86- Prefer targeted inspection tools (for example `rg` or `ast-grep`) instead of dumping entire files to
87 stdout.
88- Summarize long command results rather than echoing every line back to the user, keeping shared context
89 concise.
90
91## AVAILABLE TOOLS
92- **File Operations**: list_files, read_file, write_file, edit_file.
93- **Search & Analysis**: rg, rp_search, ast_grep_search.
94- **Terminal Access**: run_terminal_cmd for shell operations.
95- **PTY Access**: Enhanced terminal emulation for interactive commands.
96- **Advanced Analysis**: Tree-sitter parsing, performance profiling, prompt caching.
97
98## SAFETY EXPECTATIONS
99- Only access the network via the sandboxed `curl` tool. Validate HTTPS URLs, refuse localhost or private
100 targets, and tell the user which URL you fetched along with the security_notice returned by the tool.
101- Store temporary files under `/tmp/vtcode-*` and remove them when you finish using them.
102
103Your capabilities:
104- Receive user prompts and other context provided by the harness, such as files in the workspace.
105- Communicate with the user by streaming thinking & responses, and by making & updating plans.
106- Output is rendered with ANSI styles; return plain text and let the interface style the response.
107- Emit function calls to run terminal commands and apply patches.
108- Perform advanced code analysis and optimization.
109- Handle complex multi-step operations with proper error handling.
110
111Within this context, VTCode refers to the open-source agentic coding interface created by vinhnx, not any other coding tools or models."#;
112
113#[derive(Debug, Clone)]
115pub struct SystemPromptConfig {
116 pub include_examples: bool,
117 pub include_debugging_guides: bool,
118 pub include_error_handling: bool,
119 pub max_response_length: Option<usize>,
120 pub enable_thorough_reasoning: bool,
121}
122
123impl Default for SystemPromptConfig {
124 fn default() -> Self {
125 Self {
126 include_examples: true,
127 include_debugging_guides: true,
128 include_error_handling: true,
129 max_response_length: None,
130 enable_thorough_reasoning: true,
131 }
132 }
133}
134
135pub fn read_system_prompt_from_md() -> Result<String, std::io::Error> {
137 let prompt_paths = [
139 "prompts/system.md",
140 "../prompts/system.md",
141 "../../prompts/system.md",
142 ];
143
144 for path in &prompt_paths {
145 if let Ok(content) = fs::read_to_string(path) {
146 if let Some(start) = content.find("## Core System Prompt") {
148 let after_start = &content[start..];
150 if let Some(end) = after_start.find("## Specialized System Prompts") {
151 let prompt_content = &after_start[..end].trim();
152 if let Some(content_start) = prompt_content.find("```rust\nr#\"") {
154 if let Some(content_end) = prompt_content[content_start..].find("\"#\n```")
155 {
156 let prompt_start = content_start + 9; let prompt_end = content_start + content_end;
158 return Ok(prompt_content[prompt_start..prompt_end].to_string());
159 }
160 }
161 return Ok(prompt_content.to_string());
163 }
164 }
165 return Ok(content);
167 }
168 }
169
170 Ok(DEFAULT_SYSTEM_PROMPT.to_string())
172}
173
174pub fn generate_system_instruction(_config: &SystemPromptConfig) -> Content {
176 match read_system_prompt_from_md() {
177 Ok(prompt_content) => Content::system_text(prompt_content),
178 Err(_) => Content::system_text(DEFAULT_SYSTEM_PROMPT.to_string()),
179 }
180}
181
182pub fn read_agent_guidelines(project_root: &Path) -> Option<String> {
184 match read_project_doc(project_root, project_doc_constants::DEFAULT_MAX_BYTES) {
185 Ok(Some(bundle)) => Some(bundle.contents),
186 Ok(None) => None,
187 Err(err) => {
188 warn!("failed to load project documentation: {err:#}");
189 None
190 }
191 }
192}
193
194pub fn generate_system_instruction_with_config(
196 _config: &SystemPromptConfig,
197 project_root: &Path,
198 vtcode_config: Option<&crate::config::VTCodeConfig>,
199) -> Content {
200 let mut instruction = match read_system_prompt_from_md() {
201 Ok(content) => content,
202 Err(_) => DEFAULT_SYSTEM_PROMPT.to_string(),
203 };
204
205 if let Some(cfg) = vtcode_config {
207 instruction.push_str("\n\n## CONFIGURATION AWARENESS\n");
208 instruction
209 .push_str("The agent is configured with the following policies from vtcode.toml:\n\n");
210
211 if cfg.security.human_in_the_loop {
213 instruction.push_str("- **Human-in-the-loop**: Required for critical actions\n");
214 }
215
216 if !cfg.commands.allow_list.is_empty() {
218 instruction.push_str(&format!(
219 "- **Allowed commands**: {} commands in allow list\n",
220 cfg.commands.allow_list.len()
221 ));
222 }
223 if !cfg.commands.deny_list.is_empty() {
224 instruction.push_str(&format!(
225 "- **Denied commands**: {} commands in deny list\n",
226 cfg.commands.deny_list.len()
227 ));
228 }
229
230 if cfg.pty.enabled {
232 instruction.push_str("- **PTY functionality**: Enabled\n");
233 let (rows, cols) = (cfg.pty.default_rows, cfg.pty.default_cols);
234 instruction.push_str(&format!(
235 "- **Default terminal size**: {} rows × {} columns\n",
236 rows, cols
237 ));
238 instruction.push_str(&format!(
239 "- **PTY command timeout**: {} seconds\n",
240 cfg.pty.command_timeout_seconds
241 ));
242 } else {
243 instruction.push_str("- **PTY functionality**: Disabled\n");
244 }
245
246 instruction.push_str("\n**IMPORTANT**: Respect these configuration policies. Commands not in the allow list will require user confirmation. Always inform users when actions require confirmation due to security policies.\n");
247 }
248
249 if let Some(bundle) = read_project_guidelines(
251 project_root,
252 vtcode_config.map(|cfg| cfg.agent.project_doc_max_bytes),
253 ) {
254 instruction.push_str("\n\n## AGENTS.MD GUIDELINES\n");
255 instruction.push_str("Please follow these project-specific guidelines from AGENTS.md:\n\n");
256 instruction.push_str(&bundle.contents);
257 instruction.push_str("\n\nThese guidelines take precedence over general instructions.");
258 }
259
260 Content::system_text(instruction)
261}
262
263pub fn generate_system_instruction_with_guidelines(
265 _config: &SystemPromptConfig,
266 project_root: &Path,
267) -> Content {
268 let mut instruction = match read_system_prompt_from_md() {
269 Ok(content) => content,
270 Err(_) => DEFAULT_SYSTEM_PROMPT.to_string(),
271 };
272
273 if let Some(bundle) = read_project_guidelines(project_root, None) {
275 instruction.push_str("\n\n## AGENTS.MD GUIDELINES\n");
276 instruction.push_str("Please follow these project-specific guidelines from AGENTS.md:\n\n");
277 instruction.push_str(&bundle.contents);
278 instruction.push_str("\n\nThese guidelines take precedence over general instructions.");
279 }
280
281 Content::system_text(instruction)
282}
283
284fn read_project_guidelines(project_root: &Path, limit: Option<usize>) -> Option<ProjectDocBundle> {
285 let max_bytes = limit.unwrap_or(project_doc_constants::DEFAULT_MAX_BYTES);
286 match read_project_doc(project_root, max_bytes) {
287 Ok(Some(bundle)) => Some(bundle),
288 Ok(None) => None,
289 Err(err) => {
290 warn!("failed to load project documentation: {err:#}");
291 None
292 }
293 }
294}
295
296pub fn generate_lightweight_instruction() -> Content {
298 Content::system_text(DEFAULT_LIGHTWEIGHT_PROMPT.to_string())
299}
300
301pub fn generate_specialized_instruction() -> Content {
303 Content::system_text(DEFAULT_SPECIALIZED_PROMPT.to_string())
304}