Skip to main content

vv_agent/prompt/builder/
section.rs

1use std::sync::{Arc, Mutex};
2
3use serde_json::{json, Value};
4
5#[derive(Clone)]
6pub struct PromptSection {
7    pub id: String,
8    stable: bool,
9    compute: Arc<dyn Fn() -> String + Send + Sync>,
10    cached_value: Arc<Mutex<Option<String>>>,
11}
12
13impl PromptSection {
14    pub fn new(
15        id: impl Into<String>,
16        compute: impl Fn() -> String + Send + Sync + 'static,
17        stable: bool,
18    ) -> Self {
19        Self {
20            id: id.into(),
21            stable,
22            compute: Arc::new(compute),
23            cached_value: Arc::new(Mutex::new(None)),
24        }
25    }
26
27    pub fn constant(id: impl Into<String>, text: impl Into<String>, stable: bool) -> Self {
28        let text = text.into();
29        Self::new(id, move || text.clone(), stable)
30    }
31
32    pub fn get_value(&self) -> String {
33        if self.stable {
34            let mut cached = self.cached_value.lock().expect("prompt section cache");
35            if let Some(value) = cached.as_ref() {
36                return value.clone();
37            }
38            let value = (self.compute)();
39            *cached = Some(value.clone());
40            return value;
41        }
42        (self.compute)()
43    }
44
45    pub fn invalidate(&self) {
46        let mut cached = self.cached_value.lock().expect("prompt section cache");
47        *cached = None;
48    }
49
50    pub fn to_metadata(&self) -> Option<Value> {
51        let text = self.get_value().trim().to_string();
52        if text.is_empty() {
53            return None;
54        }
55        Some(json!({
56            "id": self.id,
57            "text": text,
58            "stable": self.stable,
59        }))
60    }
61
62    pub fn stable(&self) -> bool {
63        self.stable
64    }
65}