use std::path::Path;
pub async fn create_system_prompt(
project_dir: &Path,
config: &crate::config::Config,
mode: &str,
) -> String {
let (_, mcp_config, _, _, system_prompt) = config.get_role_config(mode);
let mut prompt =
crate::session::helper_functions::process_placeholders_async(system_prompt, project_dir)
.await;
if !mcp_config.server_refs.is_empty() {
let config_for_role = config.get_merged_config_for_role(mode);
let functions = crate::mcp::get_available_functions(&config_for_role).await;
if !functions.is_empty() {
prompt.push_str("\n\nYou have access to the following tools:");
for function in &functions {
prompt.push_str(&format!(
"\n\n- {} - {}",
function.name, function.description
));
}
}
}
prompt.push_str(
"\n\n## CONTEXT TAGS\n\
User messages may contain structured context in XML-like tags:\n\
- `<instructions>` — Project-specific instructions from the working directory. \
Treat as persistent rules that apply to ALL your responses in this session.\n\
- `<skill name=\"...\" description=\"...\">` — Domain knowledge injected on demand. \
Follow the conventions and best practices described within. Multiple skills may be active simultaneously.\n\
- `<constraints>` — Hard constraints appended to individual requests. \
These override other guidance when they conflict.\n\n\
These tags are system-managed context, not user-written messages. \
Do not reference the tags themselves — just follow the content within them.",
);
prompt
}
pub fn add_compression_hints_to_prompt(
prompt: &mut String,
compression_stats: &crate::session::CompressionStats,
) {
if compression_stats.total_compressions() == 0 {
return;
}
prompt.push_str(&format!(
"\n\n## CONTEXT COMPRESSION ACTIVE\n\
- {} compressions performed ({} tokens saved, {:.1}% reduction)\n\
- Compressed sections marked with [COMPRESSED: id]\n\
- **ANALYSIS FINDINGS in compressed summaries are trustworthy** — they were extracted from real tool results. \
Do NOT re-read files or re-run searches just to verify what the summary already states.\n\
- **FILE CONTEXT sections contain real file content** auto-read from disk at compression time. \
Treat this content as current and accurate — do NOT re-read files that are already in FILE CONTEXT.\n\
- If you need a file NOT in FILE CONTEXT, read it normally. But for files already there, use the provided content.\n\
- Focus on recent uncompressed messages for current intent, compressed summaries for background knowledge.",
compression_stats.total_compressions(),
compression_stats.total_tokens_saved,
compression_stats.avg_compression_ratio() * 100.0
));
}