Class: RubyLLM::Contract::SchemaValidator

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_llm/contract/contract/schema_validator.rb,
lib/ruby_llm/contract/contract/schema_validator/node.rb,
lib/ruby_llm/contract/contract/schema_validator/enum_rule.rb,
lib/ruby_llm/contract/contract/schema_validator/type_rule.rb,
lib/ruby_llm/contract/contract/schema_validator/bound_rule.rb,
lib/ruby_llm/contract/contract/schema_validator/object_rules.rb,
lib/ruby_llm/contract/contract/schema_validator/scalar_rules.rb,
lib/ruby_llm/contract/contract/schema_validator/schema_extractor.rb

Overview

Client-side validation of parsed output against an output_schema. Checks required fields, enum constraints, number ranges, and nested objects. This complements provider-side enforcement (with_schema) and catches violations when using Test adapter or providers that ignore schemas.

Defined Under Namespace

Classes: BoundRule, EnumRule, Node, ObjectRules, ScalarRules, SchemaExtractor, TypeRule

Constant Summary collapse

SIZE_BOUNDS =
{
  string: { min_key: :minLength, max_key: :maxLength, metric: "length" },
  array: { min_key: :minItems, max_key: :maxItems, metric: "array length" }
}.freeze
TYPE_CHECKS =
{
  "string" => ->(value) { value.is_a?(String) },
  "integer" => ->(value) { value.is_a?(Integer) },
  "number" => ->(value) { value.is_a?(Numeric) },
  "boolean" => ->(value) { value.is_a?(TrueClass) || value.is_a?(FalseClass) },
  "array" => ->(value) { value.is_a?(Array) },
  "object" => ->(value) { value.is_a?(Hash) }
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parsed_output, schema) ⇒ SchemaValidator

Returns a new instance of SchemaValidator.



35
36
37
38
39
40
41
42
# File 'lib/ruby_llm/contract/contract/schema_validator.rb', line 35

def initialize(parsed_output, schema)
  @errors = []
  json_schema = SchemaExtractor.new.call(schema)
  path = root_object_schema?(json_schema) ? nil : "root"
  @root_node = Node.new(value: parsed_output, schema: json_schema, path: path)
  @scalar_rules = ScalarRules.new(@errors)
  @object_rules = ObjectRules.new(@errors)
end

Class Method Details

.validate(parsed_output, schema) ⇒ Object



31
32
33
# File 'lib/ruby_llm/contract/contract/schema_validator.rb', line 31

def self.validate(parsed_output, schema)
  new(parsed_output, schema).validate
end

Instance Method Details

#validateObject



44
45
46
47
48
49
50
51
52
53
# File 'lib/ruby_llm/contract/contract/schema_validator.rb', line 44

def validate
  return [] unless @root_node.schema.is_a?(Hash)

  if @root_node.object_schema? && !@root_node.hash?
    ["expected object, got #{@root_node.value.class}"]
  else
    validate_root
    @errors
  end
end