simple_agents_healing/lib.rs
1//! Response healing system for SimpleAgents.
2//!
3//! Implements BAML-inspired JSON parsing and type coercion to handle malformed LLM outputs.
4//!
5//! # Architecture
6//!
7//! The healing system consists of three main components:
8//!
9//! 1. **Jsonish Parser**: Three-phase parsing strategy that handles malformed JSON
10//! - Strip & Fix: Remove markdown, fix commas, normalize quotes
11//! - Standard Parse: Try serde_json (fast path)
12//! - Lenient Parse: Character-by-character state machine
13//!
14//! 2. **Coercion Engine**: Type coercion with confidence scoring
15//! - String → Number coercion
16//! - Fuzzy field matching (case-insensitive, snake_case ↔ camelCase)
17//! - Union resolution with best-match selection
18//! - Default value injection
19//!
20//! 3. **Streaming Parser**: Incremental parsing for streaming responses
21//! - Partial value extraction
22//! - Progressive emission during streaming
23//! - Annotation support (stream.not_null, stream.done)
24//!
25//! # Example
26//!
27//! ```
28//! use simple_agents_healing::parser::JsonishParser;
29//!
30//! let malformed = r#"```json
31//! {"name": "test", "age": 25,}
32//! ```"#;
33//!
34//! let parser = JsonishParser::new();
35//! let result = parser.parse(malformed).unwrap();
36//!
37//! assert_eq!(result.value["name"], "test");
38//! assert_eq!(result.value["age"], 25);
39//! assert!(result.flags.iter().any(|f| matches!(f,
40//! simple_agent_type::coercion::CoercionFlag::StrippedMarkdown)));
41//! ```
42//!
43//! # Transparency
44//!
45//! All transformations are tracked via [`CoercionFlag`]s and assigned confidence scores:
46//!
47//! - **1.0**: Perfect parse, no healing needed
48//! - **0.9-0.99**: Minor fixes (markdown, trailing commas)
49//! - **0.7-0.89**: Type coercion or fuzzy field matching
50//! - **0.5-0.69**: Multiple coercions or truncation
51//! - **<0.5**: Significant healing required, review recommended
52//!
53//! [`CoercionFlag`]: simple_agent_type::coercion::CoercionFlag
54
55#![deny(missing_docs)]
56#![deny(unsafe_code)]
57
58// Public modules
59pub mod coercion;
60pub mod parser;
61pub mod schema;
62pub mod streaming;
63pub mod string_utils;
64
65// Re-export commonly used types
66pub use coercion::{CoercionConfig, CoercionEngine};
67pub use parser::{JsonishParser, ParserConfig, ParserResult};
68pub use schema::{Field, ObjectSchema, Schema, StreamAnnotation};
69pub use streaming::{PartialExtractor, StreamingParser};
70
71// Re-export from simple-agent-type for convenience
72pub use simple_agent_type::coercion::{CoercionFlag, CoercionResult};
73pub use simple_agent_type::error::{HealingError, Result};
74
75/// Prelude module for convenient imports.
76pub mod prelude {
77 pub use crate::coercion::{CoercionConfig, CoercionEngine};
78 pub use crate::parser::{JsonishParser, ParserConfig, ParserResult};
79 pub use crate::schema::{Field, ObjectSchema, Schema, StreamAnnotation};
80 pub use crate::streaming::{PartialExtractor, StreamingParser};
81 pub use simple_agent_type::coercion::{CoercionFlag, CoercionResult};
82 pub use simple_agent_type::error::{HealingError, Result};
83}
84
85#[cfg(test)]
86mod tests {
87 #[test]
88 fn test_prelude_imports() {
89 use crate::prelude::*;
90
91 // Verify all types are importable
92 let _parser = JsonishParser::new();
93 let _result = CoercionResult::new(42);
94 }
95}