Skip to main content

vtcode_core/prompts/
templates.rs

1use super::config::{AgentPersonality, ResponseStyle};
2use crate::tools::registry::{UnifiedExecAction, UnifiedFileAction, UnifiedSearchAction};
3use once_cell::sync::Lazy;
4
5static TOOL_USAGE_PROMPT: Lazy<String> = Lazy::new(|| {
6    let search_actions = UnifiedSearchAction::documented_labels().join("/");
7    let file_actions = UnifiedFileAction::documented_labels().join("/");
8    let exec_actions = UnifiedExecAction::documented_labels().join("/");
9    format!(
10        "Tools: unified_search ({search_actions}; default to structural for code search and grep for plain text), unified_file ({file_actions}), unified_exec ({exec_actions}), request_user_input (interactive-only when enabled; unavailable in non-interactive runtimes), and apply_patch (first-class patch tool when exposed by the model). Paths for unified_search and unified_file are relative to the workspace root. Use unified_search `action=list` for file discovery and unified_file `action=read` for file contents; avoid using unified_exec with `ls`, `find`, `cat`, or `sed` for ordinary repo browsing when the public tools can express the task. Treat read_file/write_file/edit_file/grep_file/PTy helpers as compatibility aliases or internal routes; prefer the canonical public tools, and prefer `rg` over shell `grep` when command search is required."
11    )
12});
13
14/// Prompt template collection
15pub struct PromptTemplates;
16
17impl PromptTemplates {
18    /// Get base system prompt
19    pub fn base_system_prompt() -> &'static str {
20        "You are a helpful AI coding assistant. You provide accurate, helpful responses and can execute tools to assist with coding tasks."
21    }
22
23    /// Get personality-specific prompt addition
24    pub fn personality_prompt(personality: &AgentPersonality) -> &'static str {
25        match personality {
26            AgentPersonality::Professional => {
27                "Maintain a professional, focused approach to problem-solving."
28            }
29            AgentPersonality::Friendly => {
30                "Be friendly and encouraging while helping with coding tasks."
31            }
32            AgentPersonality::Technical => {
33                "Provide detailed technical explanations and focus on best practices."
34            }
35            AgentPersonality::Creative => {
36                "Think creatively and suggest innovative solutions to problems."
37            }
38        }
39    }
40
41    /// Get response style prompt addition
42    pub fn response_style_prompt(style: &ResponseStyle) -> &'static str {
43        match style {
44            ResponseStyle::Concise => "Keep responses concise and to the point.",
45            ResponseStyle::Detailed => "Provide detailed explanations and comprehensive answers.",
46            ResponseStyle::Conversational => {
47                "Use a conversational tone and explain concepts clearly."
48            }
49            ResponseStyle::Technical => {
50                "Focus on technical accuracy and include relevant implementation details."
51            }
52        }
53    }
54
55    /// Get tool usage prompt
56    pub fn tool_usage_prompt() -> &'static str {
57        TOOL_USAGE_PROMPT.as_str()
58    }
59
60    /// Get workspace context prompt
61    pub fn workspace_context_prompt() -> &'static str {
62        "Work within project workspace. Consider existing code structure."
63    }
64
65    /// Get safety guidelines prompt
66    pub fn safety_guidelines_prompt() -> &'static str {
67        "Safety: Follow permissions, confirm destructive ops, retry tool errors with corrected args."
68    }
69
70    /// Get pagination guidelines prompt
71    pub fn pagination_guidelines_prompt() -> &'static str {
72        "Pagination: per_page=50 default, reduce to 25 for large dirs, check 'has_more' flag."
73    }
74
75    /// Get skills available prompt (inspired by OpenAI Codex)
76    pub fn skills_available_prompt() -> &'static str {
77        "## Skills\nSpecialized capabilities from .agents/skills/. Use list_skills to discover skills by name and description, load_skill to activate, and load_skill_resource for deeper assets. For deterministic workflows, explicitly say `Use the <skill> skill`."
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::PromptTemplates;
84    use crate::tools::registry::{UnifiedExecAction, UnifiedFileAction, UnifiedSearchAction};
85
86    #[test]
87    fn skills_prompt_mentions_description_routing() {
88        let prompt = PromptTemplates::skills_available_prompt();
89        assert!(prompt.contains("name and description"));
90        assert!(prompt.contains("Use the <skill> skill"));
91    }
92
93    #[test]
94    fn tool_usage_prompt_prefers_public_repo_browsing_tools() {
95        let prompt = PromptTemplates::tool_usage_prompt();
96        assert!(prompt.contains("relative to the workspace root"));
97        assert!(prompt.contains("action=list"));
98        assert!(prompt.contains("action=read"));
99        assert!(prompt.contains("avoid using unified_exec"));
100    }
101
102    #[test]
103    fn tool_usage_prompt_tracks_documented_unified_actions() {
104        let prompt = PromptTemplates::tool_usage_prompt();
105        for action in UnifiedExecAction::documented_labels() {
106            assert!(
107                prompt.contains(action),
108                "missing unified_exec action {action}"
109            );
110        }
111        for action in UnifiedFileAction::documented_labels() {
112            assert!(
113                prompt.contains(action),
114                "missing unified_file action {action}"
115            );
116        }
117        for action in UnifiedSearchAction::documented_labels() {
118            assert!(
119                prompt.contains(action),
120                "missing unified_search action {action}"
121            );
122        }
123    }
124}