1use serde::{Deserialize, Serialize};
5
6use crate::defaults::default_true;
7
8fn default_max_content_size() -> usize {
13 65_536
14}
15
16#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
19pub struct ContentIsolationConfig {
20 #[serde(default = "default_true")]
22 pub enabled: bool,
23
24 #[serde(default = "default_max_content_size")]
26 pub max_content_size: usize,
27
28 #[serde(default = "default_true")]
31 pub flag_injection_patterns: bool,
32
33 #[serde(default = "default_true")]
36 pub spotlight_untrusted: bool,
37
38 #[serde(default)]
40 pub quarantine: QuarantineConfig,
41}
42
43impl Default for ContentIsolationConfig {
44 fn default() -> Self {
45 Self {
46 enabled: true,
47 max_content_size: default_max_content_size(),
48 flag_injection_patterns: true,
49 spotlight_untrusted: true,
50 quarantine: QuarantineConfig::default(),
51 }
52 }
53}
54
55#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
58pub struct QuarantineConfig {
59 #[serde(default)]
61 pub enabled: bool,
62
63 #[serde(default = "default_quarantine_sources")]
65 pub sources: Vec<String>,
66
67 #[serde(default = "default_quarantine_model")]
69 pub model: String,
70}
71
72fn default_quarantine_sources() -> Vec<String> {
73 vec!["web_scrape".to_owned(), "a2a_message".to_owned()]
74}
75
76fn default_quarantine_model() -> String {
77 "claude".to_owned()
78}
79
80impl Default for QuarantineConfig {
81 fn default() -> Self {
82 Self {
83 enabled: false,
84 sources: default_quarantine_sources(),
85 model: default_quarantine_model(),
86 }
87 }
88}
89
90#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
97pub struct ExfiltrationGuardConfig {
98 #[serde(default = "default_true")]
100 pub block_markdown_images: bool,
101
102 #[serde(default = "default_true")]
104 pub validate_tool_urls: bool,
105
106 #[serde(default = "default_true")]
108 pub guard_memory_writes: bool,
109}
110
111impl Default for ExfiltrationGuardConfig {
112 fn default() -> Self {
113 Self {
114 block_markdown_images: true,
115 validate_tool_urls: true,
116 guard_memory_writes: true,
117 }
118 }
119}
120
121fn default_max_content_bytes() -> usize {
126 4096
127}
128
129fn default_max_entity_name_bytes() -> usize {
130 256
131}
132
133fn default_min_entity_name_bytes() -> usize {
134 3
135}
136
137fn default_max_fact_bytes() -> usize {
138 1024
139}
140
141fn default_max_entities() -> usize {
142 50
143}
144
145fn default_max_edges() -> usize {
146 100
147}
148
149#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
153pub struct MemoryWriteValidationConfig {
154 #[serde(default = "default_true")]
156 pub enabled: bool,
157 #[serde(default = "default_max_content_bytes")]
159 pub max_content_bytes: usize,
160 #[serde(default = "default_min_entity_name_bytes")]
162 pub min_entity_name_bytes: usize,
163 #[serde(default = "default_max_entity_name_bytes")]
165 pub max_entity_name_bytes: usize,
166 #[serde(default = "default_max_fact_bytes")]
168 pub max_fact_bytes: usize,
169 #[serde(default = "default_max_entities")]
171 pub max_entities_per_extraction: usize,
172 #[serde(default = "default_max_edges")]
174 pub max_edges_per_extraction: usize,
175 #[serde(default)]
177 pub forbidden_content_patterns: Vec<String>,
178}
179
180impl Default for MemoryWriteValidationConfig {
181 fn default() -> Self {
182 Self {
183 enabled: true,
184 max_content_bytes: default_max_content_bytes(),
185 min_entity_name_bytes: default_min_entity_name_bytes(),
186 max_entity_name_bytes: default_max_entity_name_bytes(),
187 max_fact_bytes: default_max_fact_bytes(),
188 max_entities_per_extraction: default_max_entities(),
189 max_edges_per_extraction: default_max_edges(),
190 forbidden_content_patterns: Vec::new(),
191 }
192 }
193}
194
195#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
201pub struct CustomPiiPattern {
202 pub name: String,
204 pub pattern: String,
206 #[serde(default = "default_custom_replacement")]
208 pub replacement: String,
209}
210
211fn default_custom_replacement() -> String {
212 "[PII:custom]".to_owned()
213}
214
215#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
219#[allow(clippy::struct_excessive_bools)]
220pub struct PiiFilterConfig {
221 #[serde(default)]
223 pub enabled: bool,
224 #[serde(default = "default_true")]
226 pub filter_email: bool,
227 #[serde(default = "default_true")]
229 pub filter_phone: bool,
230 #[serde(default = "default_true")]
232 pub filter_ssn: bool,
233 #[serde(default = "default_true")]
235 pub filter_credit_card: bool,
236 #[serde(default)]
238 pub custom_patterns: Vec<CustomPiiPattern>,
239}
240
241impl Default for PiiFilterConfig {
242 fn default() -> Self {
243 Self {
244 enabled: false,
245 filter_email: true,
246 filter_phone: true,
247 filter_ssn: true,
248 filter_credit_card: true,
249 custom_patterns: Vec::new(),
250 }
251 }
252}
253
254#[cfg(feature = "guardrail")]
260#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Deserialize, Serialize)]
261#[serde(rename_all = "lowercase")]
262pub enum GuardrailAction {
263 #[default]
265 Block,
266 Warn,
268}
269
270#[cfg(feature = "guardrail")]
272#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Deserialize, Serialize)]
273#[serde(rename_all = "lowercase")]
274pub enum GuardrailFailStrategy {
275 #[default]
277 Closed,
278 Open,
280}
281
282#[cfg(feature = "guardrail")]
284#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
285pub struct GuardrailConfig {
286 #[serde(default)]
288 pub enabled: bool,
289 #[serde(default)]
291 pub provider: Option<String>,
292 #[serde(default)]
294 pub model: Option<String>,
295 #[serde(default = "default_guardrail_timeout_ms")]
297 pub timeout_ms: u64,
298 #[serde(default)]
300 pub action: GuardrailAction,
301 #[serde(default = "default_fail_strategy")]
303 pub fail_strategy: GuardrailFailStrategy,
304 #[serde(default)]
306 pub scan_tool_output: bool,
307 #[serde(default = "default_max_input_chars")]
309 pub max_input_chars: usize,
310}
311
312#[cfg(feature = "guardrail")]
313fn default_guardrail_timeout_ms() -> u64 {
314 500
315}
316
317#[cfg(feature = "guardrail")]
318fn default_max_input_chars() -> usize {
319 4096
320}
321
322#[cfg(feature = "guardrail")]
323fn default_fail_strategy() -> GuardrailFailStrategy {
324 GuardrailFailStrategy::Closed
325}
326
327#[cfg(feature = "guardrail")]
328impl Default for GuardrailConfig {
329 fn default() -> Self {
330 Self {
331 enabled: false,
332 provider: None,
333 model: None,
334 timeout_ms: default_guardrail_timeout_ms(),
335 action: GuardrailAction::default(),
336 fail_strategy: default_fail_strategy(),
337 scan_tool_output: false,
338 max_input_chars: default_max_input_chars(),
339 }
340 }
341}
342
343#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
353pub struct ResponseVerificationConfig {
354 #[serde(default = "default_true")]
356 pub enabled: bool,
357 #[serde(default)]
363 pub block_on_detection: bool,
364}
365
366impl Default for ResponseVerificationConfig {
367 fn default() -> Self {
368 Self {
369 enabled: true,
370 block_on_detection: false,
371 }
372 }
373}