use simple_agents_healing::schema::{Field, ObjectSchema, StreamAnnotation};
use simple_agents_healing::streaming::PartialExtractor;
use simple_agents_healing::Schema;
fn main() {
println!("🏷️ SimpleAgents - Streaming Annotations Example\n");
let schema = ObjectSchema::new(vec![
Field::optional("id", Schema::String).with_stream_annotation(StreamAnnotation::NotNull),
Field::required("name", Schema::String).with_stream_annotation(StreamAnnotation::Normal),
Field::required("status", Schema::String).with_stream_annotation(StreamAnnotation::Done),
Field::optional("progress", Schema::UInt).with_stream_annotation(StreamAnnotation::Normal),
]);
println!("📋 Schema with annotations:");
for field in &schema.fields {
let annotation = match field.stream_annotation {
StreamAnnotation::Normal => "Normal (emit immediately)",
StreamAnnotation::NotNull => "NotNull (wait for non-null)",
StreamAnnotation::Done => "Done (wait for complete)",
};
println!(" • {}: {}", field.name, annotation);
}
println!();
let chunks = [
r#"{"id": null, "name": "Task 1""#,
r#", "progress": 10"#,
r#", "status": "in_progr"#,
r#"ess", "id": "task_123"}"#,
];
let mut extractor = PartialExtractor::new();
println!("📥 Processing streaming chunks:\n");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
for (i, chunk) in chunks.iter().enumerate() {
println!("\nChunk {}: {}", i + 1, chunk);
if let Some(partial) = extractor.feed(chunk) {
println!(" Emitted fields:");
let id_annotation = schema
.fields
.iter()
.find(|f| f.name == "id")
.map(|f| f.stream_annotation)
.unwrap_or(StreamAnnotation::Normal);
let status_annotation = schema
.fields
.iter()
.find(|f| f.name == "status")
.map(|f| f.stream_annotation)
.unwrap_or(StreamAnnotation::Normal);
if let Some(id) = partial.get("id") {
match id_annotation {
StreamAnnotation::NotNull => {
if !id.is_null() {
println!(" ✓ id: {} (NotNull satisfied)", id);
} else {
println!(" ⏸ id: null (waiting for NotNull)");
}
}
_ => println!(" ✓ id: {}", id),
}
}
if let Some(name) = partial.get("name") {
println!(" ✓ name: {} (Normal emission)", name);
}
if let Some(progress) = partial.get("progress") {
println!(" ✓ progress: {} (Normal emission)", progress);
}
if let Some(status) = partial.get("status") {
match status_annotation {
StreamAnnotation::Done => {
if let Some(s) = status.as_str() {
if s.len() > 5 && !s.contains('"') {
println!(" ✓ status: {} (Done - complete)", status);
} else {
println!(" ⏸ status: {} (waiting for Done)", status);
}
}
}
_ => println!(" ✓ status: {}", status),
}
}
}
}
println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
match extractor.finalize() {
Ok(value) => {
println!("\n✅ Stream complete!");
println!(" Final value: {}", value);
}
Err(e) => {
println!("\n❌ Stream error: {}", e);
}
}
println!("\n💡 Annotation Benefits:");
println!(" • NotNull: Avoid emitting null placeholders");
println!(" • Done: Wait for complete values (e.g., full sentences)");
println!(" • Normal: Stream data as fast as possible");
println!(" • Field-level control over emission timing");
}