Skip to main content

ai_agents_eval/
redaction.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4/// String value that records whether redaction was applied.
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct RedactedString {
7    /// Stored value, redacted when requested by settings.
8    pub value: String,
9    /// Whether the value was redacted for output.
10    #[serde(default)]
11    pub redacted: bool,
12}
13
14impl RedactedString {
15    pub fn plain(value: impl Into<String>) -> Self {
16        Self {
17            value: value.into(),
18            redacted: false,
19        }
20    }
21
22    pub fn redacted(value: impl Into<String>) -> Self {
23        Self {
24            value: value.into(),
25            redacted: true,
26        }
27    }
28}
29
30pub fn redact_text(text: &str, enabled: bool, max_chars: usize) -> RedactedString {
31    if !enabled {
32        return RedactedString::plain(text.to_string());
33    }
34    if max_chars == 0 {
35        return RedactedString::redacted("[redacted]");
36    }
37    let mut chars = text.chars();
38    let preview: String = chars.by_ref().take(max_chars).collect();
39    if chars.next().is_some() {
40        RedactedString::redacted(format!("{}...", preview))
41    } else {
42        RedactedString::redacted(preview)
43    }
44}
45
46pub fn redact_value(value: Value, enabled: bool, max_chars: usize) -> Value {
47    if !enabled {
48        return value;
49    }
50    match value {
51        Value::String(text) => Value::String(redact_text(&text, true, max_chars).value),
52        Value::Array(values) => Value::Array(
53            values
54                .into_iter()
55                .map(|value| redact_value(value, true, max_chars))
56                .collect(),
57        ),
58        Value::Object(map) => Value::Object(
59            map.into_iter()
60                .map(|(key, value)| (key, redact_value(value, true, max_chars)))
61                .collect(),
62        ),
63        other => other,
64    }
65}