vv_agent/memory/
microcompact.rs1use serde::{de::Error as _, Deserialize, Deserializer, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
4pub struct MicrocompactionPolicy {
5 pub trigger_ratio: f64,
6 pub target_ratio: f64,
7 pub keep_recent_cycles: u32,
8 pub min_result_chars: u32,
9}
10
11#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
12#[error("microcompaction_policy_invalid: {message}")]
13pub struct MicrocompactionPolicyError {
14 message: String,
15}
16
17#[derive(Deserialize)]
18#[serde(deny_unknown_fields)]
19struct MicrocompactionPolicyWire {
20 trigger_ratio: f64,
21 target_ratio: f64,
22 keep_recent_cycles: u32,
23 min_result_chars: u32,
24}
25
26impl Default for MicrocompactionPolicy {
27 fn default() -> Self {
28 Self {
29 trigger_ratio: 0.75,
30 target_ratio: 0.60,
31 keep_recent_cycles: 3,
32 min_result_chars: 500,
33 }
34 }
35}
36
37impl<'de> Deserialize<'de> for MicrocompactionPolicy {
38 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
39 where
40 D: Deserializer<'de>,
41 {
42 let wire = MicrocompactionPolicyWire::deserialize(deserializer)?;
43 let policy = Self {
44 trigger_ratio: wire.trigger_ratio,
45 target_ratio: wire.target_ratio,
46 keep_recent_cycles: wire.keep_recent_cycles,
47 min_result_chars: wire.min_result_chars,
48 };
49 policy.validate().map_err(D::Error::custom)?;
50 Ok(policy)
51 }
52}
53
54impl MicrocompactionPolicy {
55 pub fn new(
56 trigger_ratio: f64,
57 target_ratio: f64,
58 keep_recent_cycles: u32,
59 min_result_chars: u32,
60 ) -> Result<Self, MicrocompactionPolicyError> {
61 let policy = Self {
62 trigger_ratio,
63 target_ratio,
64 keep_recent_cycles,
65 min_result_chars,
66 };
67 policy.validate()?;
68 Ok(policy)
69 }
70
71 pub fn validate(&self) -> Result<(), MicrocompactionPolicyError> {
72 if !self.trigger_ratio.is_finite()
73 || !self.target_ratio.is_finite()
74 || self.target_ratio <= 0.0
75 || self.target_ratio >= self.trigger_ratio
76 || self.trigger_ratio > 1.0
77 {
78 return Err(MicrocompactionPolicyError {
79 message: "expected 0 < target_ratio < trigger_ratio <= 1".to_string(),
80 });
81 }
82 if self.min_result_chars == 0 {
83 return Err(MicrocompactionPolicyError {
84 message: "min_result_chars must be at least 1".to_string(),
85 });
86 }
87 Ok(())
88 }
89}