Skip to main content

vv_agent/prompt/builder/
system_builder.rs

1use serde_json::{json, Value};
2
3use super::hash::sha256_hex;
4use super::options::BuiltSystemPrompt;
5use super::section::PromptSection;
6
7#[derive(Clone, Default)]
8pub struct SystemPromptBuilder {
9    sections: Vec<PromptSection>,
10}
11
12impl SystemPromptBuilder {
13    pub fn add_section(&mut self, section: PromptSection) {
14        self.sections.push(section);
15    }
16
17    pub fn build(&self) -> String {
18        self.sections
19            .iter()
20            .filter_map(|section| {
21                let value = section.get_value().trim().to_string();
22                (!value.is_empty()).then_some(value)
23            })
24            .collect::<Vec<_>>()
25            .join("\n\n")
26    }
27
28    pub fn metadata_sections(&self) -> Vec<Value> {
29        self.sections
30            .iter()
31            .filter_map(PromptSection::to_metadata)
32            .collect()
33    }
34
35    pub fn invalidate_all(&self) {
36        for section in &self.sections {
37            section.invalidate();
38        }
39    }
40
41    pub fn invalidate_volatile(&self) {
42        for section in &self.sections {
43            if !section.stable() {
44                section.invalidate();
45            }
46        }
47    }
48
49    pub fn stable_hash(&self) -> String {
50        let stable_text = self
51            .sections
52            .iter()
53            .filter(|section| section.stable())
54            .map(|section| section.get_value().trim().to_string())
55            .collect::<String>();
56        sha256_hex(stable_text.as_bytes())
57    }
58
59    pub fn build_result(&self) -> BuiltSystemPrompt {
60        let mut prompt_parts = Vec::new();
61        let mut sections = Vec::new();
62        let mut stable_parts = Vec::new();
63        for section in &self.sections {
64            let value = section.get_value().trim().to_string();
65            if value.is_empty() {
66                continue;
67            }
68            prompt_parts.push(value.clone());
69            sections.push(json!({
70                "id": section.id,
71                "text": value,
72                "stable": section.stable(),
73            }));
74            if section.stable() {
75                stable_parts.push(value);
76            }
77        }
78        BuiltSystemPrompt {
79            prompt: prompt_parts.join("\n\n"),
80            sections,
81            stable_hash: sha256_hex(stable_parts.join("").as_bytes()),
82        }
83    }
84}