Skip to main content

agentic_config/
schema.rs

1//! JSON Schema generation for `AgenticConfig`.
2//!
3//! Uses schemars to generate a JSON Schema that can be used for
4//! IDE autocomplete and validation.
5
6use crate::types::AgenticConfig;
7use schemars::Schema;
8use schemars::generate::SchemaSettings;
9
10/// Generate the JSON Schema for `AgenticConfig`.
11pub fn schema() -> Schema {
12    SchemaSettings::default()
13        .into_generator()
14        .into_root_schema_for::<AgenticConfig>()
15}
16
17/// Generate the JSON Schema as a pretty-printed JSON string.
18pub fn schema_json_pretty() -> anyhow::Result<String> {
19    Ok(serde_json::to_string_pretty(&schema())?)
20}
21
22#[cfg(test)]
23mod tests {
24    use super::*;
25
26    #[test]
27    fn test_schema_is_valid_json() {
28        let json = schema_json_pretty().unwrap();
29        let _: serde_json::Value = serde_json::from_str(&json).unwrap();
30    }
31
32    #[test]
33    fn test_schema_has_required_properties() {
34        let schema = schema();
35        let json = serde_json::to_value(&schema).unwrap();
36
37        // Check that the schema has definitions for our types
38        assert!(json.get("$defs").is_some() || json.get("definitions").is_some());
39    }
40
41    #[test]
42    fn test_schema_excludes_secrets() {
43        let json = schema_json_pretty().unwrap();
44
45        // API keys should not appear in schema (they're skipped via #[schemars(skip)])
46        assert!(!json.contains("\"api_key\""));
47    }
48
49    #[test]
50    fn test_default_config_validates_against_schema() {
51        let schema = schema();
52        let config = AgenticConfig::default();
53        let config_json = serde_json::to_value(&config).unwrap();
54
55        // Use jsonschema crate to validate
56        let validator = jsonschema::validator_for(&serde_json::to_value(&schema).unwrap()).unwrap();
57        let result = validator.validate(&config_json);
58
59        assert!(
60            result.is_ok(),
61            "Default config should validate against schema: {:?}",
62            result.err()
63        );
64    }
65
66    #[test]
67    fn test_partial_config_validates_against_schema() {
68        let schema = schema();
69        let config_json = serde_json::json!({
70            "subagents": {
71                "locator_model": "claude-haiku-4-5"
72            }
73        });
74
75        let validator = jsonschema::validator_for(&serde_json::to_value(&schema).unwrap()).unwrap();
76        let result = validator.validate(&config_json);
77
78        assert!(
79            result.is_ok(),
80            "Partial config should validate against schema: {:?}",
81            result.err()
82        );
83    }
84}