vv_agent/prompt/builder/
section.rs1use 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}