use axon::extraction::{
clear_engine, register_engine, ExtractedSpan, ExtractionBounds, ExtractionEngine,
ExtractionError, ExtractionHint, ExtractionResult, BBox,
};
use axon::tool_executor::dispatch;
use base64::Engine;
use std::sync::Arc;
fn b64(bytes: &[u8]) -> String {
base64::engine::general_purpose::STANDARD.encode(bytes)
}
#[derive(Debug)]
struct MockEngine;
impl ExtractionEngine for MockEngine {
fn name(&self) -> &str {
"mock"
}
fn version(&self) -> &str {
"1"
}
fn extract(
&self,
_bytes: &[u8],
hint: &ExtractionHint,
_bounds: &ExtractionBounds,
) -> Result<ExtractionResult, ExtractionError> {
let t = hint.transform.clone().unwrap_or_default();
Ok(ExtractionResult {
engine: "mock".into(),
engine_version: "1".into(),
spans: vec![ExtractedSpan::new(
format!("read({t})"),
0.91,
0,
BBox { x: 0.1, y: 0.1, w: 0.3, h: 0.05 },
)],
})
}
}
#[test]
fn extraction_arms_refuse_then_serve_born_inferred() {
clear_engine();
let arg = serde_json::json!({ "bytes_base64": b64(b"%PDF-1.7 ...") }).to_string();
for tool in ["PDFExtractor", "ImageTextExtractor", "ImageAnalyzer"] {
let r = dispatch(tool, &arg).expect("native dispatch arm");
assert!(!r.success, "{tool} must refuse with no engine");
assert!(
r.output.contains("extraction.no_engine_configured"),
"{tool} → {}",
r.output
);
}
register_engine(Arc::new(MockEngine));
let expect = [
("PDFExtractor", "pdf:text"),
("ImageTextExtractor", "image:text"),
("ImageAnalyzer", "image:description"),
];
for (tool, transform) in expect {
let r = dispatch(tool, &arg).expect("native dispatch arm");
assert!(r.success, "{tool} → {}", r.output);
let v: serde_json::Value = serde_json::from_str(&r.output).unwrap();
assert_eq!(v["transform"], transform, "{tool} routed to wrong transform");
assert_eq!(v["provenance"], "inferred", "an inferred read is never parsed");
assert_eq!(v["taint"], "untrusted");
assert_eq!(v["epistemic_ceiling"], "believe", "never `know`");
assert_eq!(v["engine"], "mock");
assert!((v["mean_confidence"].as_f64().unwrap() - 0.91).abs() < 1e-9);
assert_eq!(v["spans"][0]["text"], format!("read({transform})"));
}
clear_engine();
let r = dispatch("PDFExtractor", &arg).expect("native dispatch arm");
assert!(!r.success);
assert!(r.output.contains("extraction.no_engine_configured"));
}
#[test]
fn malformed_request_is_typed_refusal_never_silent() {
let r = dispatch("PDFExtractor", "{}").expect("native dispatch arm");
assert!(!r.success);
assert!(r.output.contains("missing `bytes_base64`"), "output: {}", r.output);
let r = dispatch("ImageTextExtractor", "not json").expect("native dispatch arm");
assert!(!r.success);
assert!(r.output.contains("invalid extraction request JSON"), "output: {}", r.output);
}