agentvet 0.1.0

Validate LLM-generated tool args before execution. Throws a structured ToolArgError with LLM-friendly retry hints when the model hallucinates wrong types or missing fields.
Documentation
use crate::error::{ToolArgError, ToolArgIssue};
use serde_json::Value;

/// Validates JSON values against a JSON Schema.
pub struct Validator {
    validator: jsonschema::Validator,
}

impl Validator {
    /// Compile a validator from a JSON Schema document.
    ///
    /// Returns an error if the schema itself is malformed.
    pub fn from_schema(schema: &Value) -> Result<Self, String> {
        let validator = jsonschema::validator_for(schema).map_err(|e| e.to_string())?;
        Ok(Self { validator })
    }

    /// Validate `args` against the schema.
    ///
    /// On failure, returns a [`ToolArgError`] containing every detected
    /// issue (validation does not stop at the first error). Use
    /// [`ToolArgError::for_llm`] to render a short hint to feed the model
    /// on the next turn.
    pub fn validate(&self, args: &Value) -> Result<(), ToolArgError> {
        let issues: Vec<ToolArgIssue> = self
            .validator
            .iter_errors(args)
            .map(|err| {
                let pointer = err.instance_path.to_string();
                ToolArgIssue {
                    pointer,
                    message: err.to_string(),
                }
            })
            .collect();
        if issues.is_empty() {
            Ok(())
        } else {
            Err(ToolArgError { issues })
        }
    }

    /// True if `args` validate cleanly. Cheaper than [`validate`] when you
    /// don't need the issue list.
    pub fn is_valid(&self, args: &Value) -> bool {
        self.validator.is_valid(args)
    }
}