#![forbid(unsafe_code)]
use async_trait::async_trait;
pub use crate::url_filter::{DefaultUrlFilter, UrlFilter};
#[async_trait]
pub trait JudgeClient: Send + Sync {
async fn judge(&self, prompt: &str) -> Result<JudgeVerdict, JudgeError>;
}
#[derive(Debug, Clone)]
pub struct JudgeVerdict {
pub score: f64,
pub pass: bool,
pub reason: Option<String>,
pub label: Option<String>,
}
#[derive(Debug, thiserror::Error)]
pub enum JudgeError {
#[error("transport: {0}")]
Transport(String),
#[error("timeout")]
Timeout,
#[error("malformed response: {0}")]
MalformedResponse(String),
#[error("other: {0}")]
Other(String),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn judge_error_display_variants() {
assert_eq!(
JudgeError::Transport("boom".into()).to_string(),
"transport: boom"
);
assert_eq!(JudgeError::Timeout.to_string(), "timeout");
assert_eq!(
JudgeError::MalformedResponse("bad".into()).to_string(),
"malformed response: bad"
);
assert_eq!(
JudgeError::Other("thing".into()).to_string(),
"other: thing"
);
}
#[test]
fn verdict_fields_are_public() {
let v = JudgeVerdict {
score: 0.75,
pass: true,
reason: Some("looks right".into()),
label: Some("equivalent".into()),
};
assert!((v.score - 0.75).abs() < f64::EPSILON);
assert!(v.pass);
assert_eq!(v.reason.as_deref(), Some("looks right"));
assert_eq!(v.label.as_deref(), Some("equivalent"));
}
}