Module: OllamaAgent::LLM::PlannerSchema
- Defined in:
- lib/ollama_agent/llm/planner_schema.rb
Overview
Validates a parsed JSON Hash against a small JSON-schema-shaped allowlist.
Constant Summary collapse
- VALID_JSON_TYPES =
%w[string array object number boolean].freeze
Class Method Summary collapse
- .check_no_extra_keys(obj, allowed) ⇒ Object
- .check_property_types(obj, props) ⇒ Object
- .check_required(obj, schema) ⇒ Object
- .match_property_type(value, spec) ⇒ Object
- .matches_json_type?(value, want) ⇒ Boolean
- .stringify_keys_shallow(hash) ⇒ Object
- .validate(obj, schema) ⇒ Object
- .validate_root_object(obj, schema) ⇒ Object
Class Method Details
.check_no_extra_keys(obj, allowed) ⇒ Object
44 45 46 47 48 49 |
# File 'lib/ollama_agent/llm/planner_schema.rb', line 44 def check_no_extra_keys(obj, allowed) obj.each_key do |key| return "extra key #{key}" unless allowed.include?(key.to_s) end nil end |
.check_property_types(obj, props) ⇒ Object
51 52 53 54 55 56 57 58 59 |
# File 'lib/ollama_agent/llm/planner_schema.rb', line 51 def check_property_types(obj, props) props.each do |key, spec| next unless obj.key?(key) ok, err = match_property_type(obj[key], spec) return err unless ok end nil end |
.check_required(obj, schema) ⇒ Object
36 37 38 39 40 41 42 |
# File 'lib/ollama_agent/llm/planner_schema.rb', line 36 def check_required(obj, schema) required_keys = Array(schema["required"] || schema[:required]).map(&:to_s) required_keys.each do |key| return "missing required key #{key}" unless obj.key?(key) end nil end |
.match_property_type(value, spec) ⇒ Object
61 62 63 64 65 66 67 68 69 |
# File 'lib/ollama_agent/llm/planner_schema.rb', line 61 def match_property_type(value, spec) want = (spec["type"] || spec[:type]).to_s return [false, "unknown or missing type for #{want}"] unless VALID_JSON_TYPES.include?(want) ok = matches_json_type?(value, want) return [true, nil] if ok [false, "type mismatch for value #{value.inspect} (expected #{want})"] end |
.matches_json_type?(value, want) ⇒ Boolean
71 72 73 74 75 76 77 78 79 80 |
# File 'lib/ollama_agent/llm/planner_schema.rb', line 71 def matches_json_type?(value, want) case want when "string" then value.is_a?(String) when "array" then value.is_a?(Array) when "object" then value.is_a?(Hash) when "boolean" then [true, false].include?(value) when "number" then value.is_a?(Integer) || value.is_a?(Float) else false end end |
.stringify_keys_shallow(hash) ⇒ Object
82 83 84 85 86 |
# File 'lib/ollama_agent/llm/planner_schema.rb', line 82 def stringify_keys_shallow(hash) return {} unless hash.is_a?(Hash) hash.transform_keys(&:to_s) end |
.validate(obj, schema) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/ollama_agent/llm/planner_schema.rb', line 10 def validate(obj, schema) err = validate_root_object(obj, schema) return [false, err] if err props = stringify_keys_shallow(schema["properties"] || schema[:properties] || {}) err = check_required(obj, schema) return [false, err] if err err = check_no_extra_keys(obj, props.keys) return [false, err] if err err = check_property_types(obj, props) return [false, err] if err [true, nil] end |
.validate_root_object(obj, schema) ⇒ Object
27 28 29 30 31 32 33 34 |
# File 'lib/ollama_agent/llm/planner_schema.rb', line 27 def validate_root_object(obj, schema) return "root must be a JSON object" unless obj.is_a?(Hash) root_type = schema["type"] || schema[:type] return "schema root type must be 'object'" unless root_type.to_s == "object" nil end |