aster/prompt/
templates.rs1use super::types::{DiagnosticInfo, GitStatusInfo, IdeType, TodoItem};
6
7pub const CORE_IDENTITY: &str = r#"You are an interactive CLI tool that helps users according to your "Output Style" below, which describes how you should respond to user queries. Use the instructions below and the tools available to you to assist the user.
9
10IMPORTANT: Assist with authorized security testing, defensive security, CTF challenges, and educational contexts. Refuse requests for destructive techniques, DoS attacks, mass targeting, supply chain compromise, or detection evasion for malicious purposes.
11IMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files."#;
12
13pub const TOOL_GUIDELINES: &str = r#"# Tool usage policy
15- When doing file search, prefer to use the Task tool in order to reduce context usage.
16- You should proactively use the Task tool with specialized agents when the task at hand matches the agent's description.
17- Use specialized tools instead of bash commands when possible, as this provides a better user experience.
18- NEVER use bash echo or other command-line tools to communicate thoughts, explanations, or instructions to the user.
19- When exploring the codebase to gather context, use the Task tool with subagent_type=Explore instead of running search commands directly."#;
20
21pub mod permission_modes {
23 pub const DEFAULT: &str = r#"# Permission Mode: Default
24You are running in default mode. You must ask for user approval before:
25- Writing or editing files
26- Running bash commands
27- Making network requests"#;
28
29 pub const ACCEPT_EDITS: &str = r#"# Permission Mode: Accept Edits
30You are running in accept-edits mode. File edits are automatically approved.
31You still need to ask for approval for:
32- Running bash commands that could be dangerous
33- Making network requests to external services"#;
34
35 pub const BYPASS: &str = r#"# Permission Mode: Bypass
36You are running in bypass mode. All tool calls are automatically approved.
37Use this mode responsibly and only when explicitly requested."#;
38
39 pub const PLAN: &str = r#"# Permission Mode: Plan
40You are running in plan mode. You should:
411. Thoroughly explore the codebase using Glob, Grep, and Read tools
422. Understand existing patterns and architecture
433. Design an implementation approach
444. Present your plan to the user for approval
455. Exit plan mode with ExitPlanMode when ready to implement"#;
46
47 pub const DELEGATE: &str = r#"# Permission Mode: Delegate
48You are running as a delegated subagent. Permission decisions are delegated to the parent agent.
49Complete your task autonomously without asking for user input."#;
50
51 pub const DONT_ASK: &str = r#"# Permission Mode: Don't Ask
52You are running in don't-ask mode. Permissions are determined by configured rules.
53Follow the rules defined in the configuration without prompting the user."#;
54}
55
56pub const OUTPUT_STYLE: &str = r#"# Tone and style
58- Only use emojis if the user explicitly requests it.
59- Your output will be displayed on a command line interface. Your responses should be short and concise.
60- Output text to communicate with the user; all text you output outside of tool use is displayed to the user.
61- NEVER create files unless they're absolutely necessary for achieving your goal.
62
63# Professional objectivity
64Prioritize technical accuracy and truthfulness over validating the user's beliefs. Focus on facts and problem-solving."#;
65
66pub const GIT_GUIDELINES: &str = r#"# Git Operations
68- NEVER update the git config
69- NEVER run destructive/irreversible git commands (like push --force, hard reset) unless explicitly requested
70- NEVER skip hooks (--no-verify, --no-gpg-sign) unless explicitly requested
71- NEVER force push to main/master
72- Avoid git commit --amend unless explicitly requested
73- NEVER commit changes unless the user explicitly asks"#;
74
75pub const TASK_MANAGEMENT: &str = r#"# Task Management
77You have access to the TodoWrite tools to help you manage and plan tasks. Use these tools VERY frequently to ensure that you are tracking your tasks and giving the user visibility into your progress.
78These tools are also EXTREMELY helpful for planning tasks, and for breaking down larger complex tasks into smaller steps."#;
79
80pub const CODING_GUIDELINES: &str = r#"# Doing tasks
82- NEVER propose changes to code you haven't read. If a user asks about or wants you to modify a file, read it first.
83- Use the TodoWrite tool to plan the task if required
84- Be careful not to introduce security vulnerabilities such as command injection, XSS, SQL injection.
85- Avoid over-engineering. Only make changes that are directly requested or clearly necessary."#;
86
87pub const SUBAGENT_SYSTEM: &str = r#"# Subagent System
89When exploring the codebase to gather context or answer questions that may require multiple rounds of searching:
90- Use the Task tool with subagent_type=Explore for codebase exploration
91- Use the Task tool with subagent_type=Plan for implementation planning"#;
92
93pub fn get_permission_mode_description(mode: &str) -> &'static str {
95 match mode {
96 "default" => permission_modes::DEFAULT,
97 "accept_edits" | "acceptEdits" => permission_modes::ACCEPT_EDITS,
98 "bypass" | "bypassPermissions" => permission_modes::BYPASS,
99 "plan" => permission_modes::PLAN,
100 "delegate" => permission_modes::DELEGATE,
101 "dont_ask" | "dontAsk" => permission_modes::DONT_ASK,
102 _ => permission_modes::DEFAULT,
103 }
104}
105
106pub struct EnvironmentInfo<'a> {
108 pub working_dir: &'a str,
109 pub is_git_repo: bool,
110 pub platform: &'a str,
111 pub today_date: &'a str,
112 pub model: Option<&'a str>,
113}
114
115pub fn get_environment_info(info: &EnvironmentInfo) -> String {
117 let mut lines = vec![
118 "<environment>".to_string(),
119 format!("Working directory: {}", info.working_dir),
120 format!("Is git repo: {}", info.is_git_repo),
121 format!("Platform: {}", info.platform),
122 format!("Today: {}", info.today_date),
123 ];
124
125 if let Some(model) = info.model {
126 lines.push(format!("Model: {}", model));
127 }
128
129 lines.push("</environment>".to_string());
130 lines.join("\n")
131}
132
133pub fn get_ide_info(
135 ide_type: Option<IdeType>,
136 ide_selection: Option<&str>,
137 ide_opened_files: Option<&[String]>,
138) -> String {
139 let mut lines = vec!["<ide-info>".to_string()];
140
141 if let Some(ide) = ide_type {
142 lines.push(format!("IDE: {:?}", ide));
143 }
144
145 if let Some(selection) = ide_selection {
146 lines.push(format!("Selected code:\n```\n{}\n```", selection));
147 }
148
149 if let Some(files) = ide_opened_files {
150 if !files.is_empty() {
151 lines.push("Opened files:".to_string());
152 for file in files {
153 lines.push(format!(" - {}", file));
154 }
155 }
156 }
157
158 lines.push("</ide-info>".to_string());
159 lines.join("\n")
160}
161
162pub fn get_diagnostics_info(diagnostics: &[DiagnosticInfo]) -> Option<String> {
164 if diagnostics.is_empty() {
165 return None;
166 }
167
168 let mut lines = vec!["<diagnostics>".to_string()];
169
170 for diag in diagnostics {
171 let severity = format!("{:?}", diag.severity).to_uppercase();
172 lines.push(format!(
173 "[{}] {}:{}:{} - {}",
174 severity, diag.file, diag.line, diag.column, diag.message
175 ));
176 }
177
178 lines.push("</diagnostics>".to_string());
179 Some(lines.join("\n"))
180}
181
182pub fn get_git_status_info(status: &GitStatusInfo) -> String {
184 let mut lines = vec![
185 "<git-status>".to_string(),
186 format!("Branch: {}", status.branch),
187 format!("Clean: {}", status.is_clean),
188 ];
189
190 if status.ahead > 0 || status.behind > 0 {
191 lines.push(format!(
192 "Ahead: {}, Behind: {}",
193 status.ahead, status.behind
194 ));
195 }
196
197 if !status.staged.is_empty() {
198 lines.push(format!("Staged: {}", status.staged.join(", ")));
199 }
200
201 if !status.unstaged.is_empty() {
202 lines.push(format!("Unstaged: {}", status.unstaged.join(", ")));
203 }
204
205 if !status.untracked.is_empty() {
206 lines.push(format!("Untracked: {}", status.untracked.join(", ")));
207 }
208
209 lines.push("</git-status>".to_string());
210 lines.join("\n")
211}
212
213pub fn get_memory_info(memory: &std::collections::HashMap<String, String>) -> Option<String> {
215 if memory.is_empty() {
216 return None;
217 }
218
219 let mut lines = vec!["<memory>".to_string()];
220
221 for (key, value) in memory {
222 lines.push(format!("## {}\n{}", key, value));
223 }
224
225 lines.push("</memory>".to_string());
226 Some(lines.join("\n"))
227}
228
229pub fn get_todo_list_info(todos: &[TodoItem]) -> Option<String> {
231 if todos.is_empty() {
232 return None;
233 }
234
235 let mut lines = vec!["# Current Tasks".to_string()];
236
237 for todo in todos {
238 let status_icon = match todo.status {
239 super::types::TodoStatus::Pending => "[ ]",
240 super::types::TodoStatus::InProgress => "[~]",
241 super::types::TodoStatus::Completed => "[x]",
242 };
243 lines.push(format!("{} {}", status_icon, todo.content));
244 }
245
246 Some(lines.join("\n"))
247}