Skip to main content

aster/prompt/
templates.rs

1//! 系统提示词模板
2//!
3//! 模块化的提示词组件
4
5use super::types::{DiagnosticInfo, GitStatusInfo, IdeType, TodoItem};
6
7/// 核心身份描述
8pub 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
13/// 工具使用指南
14pub 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
21/// 权限模式说明
22pub 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
56/// 输出风格指令
57pub 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
66/// Git 操作指南
67pub 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
75/// 任务管理指南
76pub 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
80/// 代码编写指南
81pub 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
87/// 子代理系统说明
88pub 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
93/// 获取权限模式描述
94pub 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
106/// 环境信息
107pub 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
115/// 获取环境信息文本
116pub 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
133/// 获取 IDE 信息文本
134pub 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
162/// 获取诊断信息文本
163pub 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
182/// 获取 Git 状态信息文本
183pub 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
213/// 获取记忆信息文本
214pub 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
229/// 获取任务列表信息文本
230pub 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}