use crate::errors::Result;
use crate::utils::{sanitize, SanitizeAction};
use serde_json::Value;
pub trait Sanitizer: Send + Sync {
fn sanitize(&self, content: &str) -> (String, SanitizeAction);
}
pub struct DefaultSanitizer;
impl Sanitizer for DefaultSanitizer {
fn sanitize(&self, content: &str) -> (String, SanitizeAction) {
sanitize(content)
}
}
pub struct NoopSanitizer;
impl Sanitizer for NoopSanitizer {
fn sanitize(&self, content: &str) -> (String, SanitizeAction) {
(content.to_string(), SanitizeAction::Allow)
}
}
pub trait Refiner: Send + Sync {
fn refine(&self, chunks: Vec<Value>, budget_tokens: Option<usize>) -> Result<Vec<Value>>;
fn trim(&self, _block: &[Value], _query: &str, _budget_tokens: usize) -> Option<Vec<Value>> {
None
}
}
pub struct NullRefiner;
impl Refiner for NullRefiner {
fn refine(&self, chunks: Vec<Value>, _budget: Option<usize>) -> Result<Vec<Value>> {
Ok(chunks)
}
}
pub trait Distiller: Send + Sync {
fn distill(&self, log_entries: &[Value]) -> Result<Vec<DistilledChunk>>;
}
#[derive(Debug, Clone)]
pub struct DistilledChunk {
pub content: String,
pub trigger_desc: Option<String>,
pub anti_trigger_desc: Option<String>,
pub source_log_id: String,
pub nomination: Option<String>,
}
pub struct HeuristicDistiller;
impl Distiller for HeuristicDistiller {
fn distill(&self, log_entries: &[Value]) -> Result<Vec<DistilledChunk>> {
let mut out = Vec::new();
for entry in log_entries {
let id = entry["id"].as_str().unwrap_or("").to_string();
let text = entry["nomination"]
.as_str()
.or_else(|| entry["output_summary"].as_str());
if let Some(t) = text {
let t = t.trim();
if !t.is_empty() {
let trigger_desc = entry["query"]
.as_str()
.map(|q| q.trim().chars().take(80).collect::<String>())
.filter(|q| !q.is_empty())
.or_else(|| {
t.lines()
.map(str::trim)
.find(|l| l.len() > 10)
.map(|l| l.chars().take(80).collect())
});
out.push(DistilledChunk {
content: t.to_string(),
trigger_desc,
anti_trigger_desc: None,
source_log_id: id,
nomination: entry["nomination"].as_str().map(str::to_string),
});
}
}
}
Ok(out)
}
}