ai-agent 0.88.0

Idiomatic agent sdk inspired by the claude code source leak
Documentation
use serde_json::{json, Value};

pub fn validate_json_schema(data: &Value, schema: &Value) -> Result<(), String> {
    if let Some(schema_type) = schema.get("type") {
        match schema_type.as_str() {
            Some("object") => {
                if !data.is_object() {
                    return Err("Expected object".to_string());
                }
                if let Some(properties) = schema.get("properties") {
                    if let Some(obj) = data.as_object() {
                        for (key, value) in obj {
                            if let Some(prop_schema) = properties.get(key) {
                                validate_json_schema(value, prop_schema)?;
                            }
                        }
                    }
                }
            }
            Some("array") => {
                if !data.is_array() {
                    return Err("Expected array".to_string());
                }
                if let Some(items) = schema.get("items") {
                    if let Some(arr) = data.as_array() {
                        for item in arr {
                            validate_json_schema(item, items)?;
                        }
                    }
                }
            }
            Some("string") => {
                if !data.is_string() {
                    return Err("Expected string".to_string());
                }
            }
            Some("number") | Some("integer") => {
                if !data.is_number() {
                    return Err("Expected number".to_string());
                }
            }
            Some("boolean") => {
                if !data.is_boolean() {
                    return Err("Expected boolean".to_string());
                }
            }
            Some("null") => {
                if !data.is_null() {
                    return Err("Expected null".to_string());
                }
            }
            _ => {}
        }
    }
    Ok(())
}

pub fn generate_schema_for_type(value: &Value) -> Value {
    match value {
        Value::Null => json!({"type": "null"}),
        Value::Bool(_) => json!({"type": "boolean"}),
        Value::Number(_) => json!({"type": "number"}),
        Value::String(_) => json!({"type": "string"}),
        Value::Array(arr) => {
            if let Some(first) = arr.first() {
                json!({"type": "array", "items": generate_schema_for_type(first)})
            } else {
                json!({"type": "array"})
            }
        }
        Value::Object(obj) => {
            let properties: serde_json::Map<String, Value> = obj
                .iter()
                .map(|(k, v)| (k.clone(), generate_schema_for_type(v)))
                .collect();
            json!({"type": "object", "properties": properties})
        }
    }
}