use crate::system::SystemInfo;
use handlebars::Handlebars;
use rust_embed::RustEmbed;
use serde_json::json;
#[derive(RustEmbed)]
#[folder = "static/prompts/"]
struct PromptAssets;
pub struct PromptBuilder {
system_info: SystemInfo,
handlebars: Handlebars<'static>,
}
impl PromptBuilder {
pub fn new(system_info: SystemInfo) -> Self {
Self {
system_info,
handlebars: Handlebars::new(),
}
}
fn load_prompt(name: &str) -> String {
PromptAssets::get(name)
.and_then(|file| {
std::str::from_utf8(file.data.as_ref())
.ok()
.map(|s| s.to_string())
})
.unwrap_or_else(|| {
eprintln!("Warning: Failed to load prompt file: {}", name);
tracing::warn!("Failed to load prompt file: {}", name);
String::new()
})
}
fn build_common_prompt(&self) -> String {
let template = Self::load_prompt("common.md");
let data = json!({
"os": self.system_info.os.as_str(),
"shell": self.system_info.shell.as_str(),
"current_dir": self.system_info.current_dir.display().to_string(),
"username": self.system_info.username.as_deref().unwrap_or("unknown"),
"hostname": self.system_info.hostname.as_deref().unwrap_or("unknown"),
});
self.handlebars
.render_template(&template, &data)
.unwrap_or(template)
}
pub fn build_auto_mode(&self) -> String {
let common_prompt = self.build_common_prompt();
let mode_select_template = Self::load_prompt("mode_select.md");
Self::concat_prompts(vec![&common_prompt, &mode_select_template])
}
pub fn build_ask(&self) -> String {
let common_prompt = self.build_common_prompt();
let ask_prompt = Self::load_prompt("ask.md");
Self::concat_prompts(vec![&common_prompt, &ask_prompt])
}
pub fn build_suggest(&self) -> String {
let common_prompt = self.build_common_prompt();
let suggest_template = Self::load_prompt("suggest.md");
let data = json!({
"os": self.system_info.os.as_str(),
"shell": self.system_info.shell.as_str(),
});
let suggest_prompt = self
.handlebars
.render_template(&suggest_template, &data)
.unwrap_or(suggest_template);
Self::concat_prompts(vec![&common_prompt, &suggest_prompt])
}
fn concat_prompts(prompts: Vec<&str>) -> String {
prompts.join("\n\n---\n\n")
}
}