ai_agents_eval/
redaction.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct RedactedString {
7 pub value: String,
9 #[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}