Module: RCrewAI::OutputSchema
- Defined in:
- lib/rcrewai/output_schema.rb
Overview
Validates and coerces a task's raw string output against a JSON-Schema
subset (object / type / required / property types). Used by Task for the
output_schema: option. Kept intentionally small: it covers the shapes an
LLM is realistically asked to emit, not the whole JSON Schema spec.
Class Method Summary collapse
-
.coerce(raw, schema) ⇒ Object
Returns the validated/coerced object.
- .extract_json(text) ⇒ Object
-
.parse(raw) ⇒ Object
Extracts a JSON document from a string that may contain surrounding prose, then parses it.
- .raise_unless(condition, message) ⇒ Object
- .validate!(data, schema) ⇒ Object
- .validate_object!(data, schema) ⇒ Object
Class Method Details
.coerce(raw, schema) ⇒ Object
Returns the validated/coerced object. Raises OutputSchemaError if the string can't be parsed or doesn't conform.
15 16 17 18 19 |
# File 'lib/rcrewai/output_schema.rb', line 15 def coerce(raw, schema) data = parse(raw) validate!(data, schema) data end |
.extract_json(text) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/rcrewai/output_schema.rb', line 31 def extract_json(text) if (fenced = text[/```(?:json)?\s*(\{.*?\}|\[.*?\])\s*```/m, 1]) return fenced end first = text.index(/[{\[]/) last = text.rindex(/[}\]]/) return text if first.nil? || last.nil? || last < first text[first..last] end |
.parse(raw) ⇒ Object
Extracts a JSON document from a string that may contain surrounding prose, then parses it. Prefers a fenced ```json block, then the first balanced object/array, then the whole string.
24 25 26 27 28 29 |
# File 'lib/rcrewai/output_schema.rb', line 24 def parse(raw) candidate = extract_json(raw.to_s) JSON.parse(candidate) rescue JSON::ParserError => e raise OutputSchemaError, "output is not valid JSON: #{e.}" end |
.raise_unless(condition, message) ⇒ Object
73 74 75 |
# File 'lib/rcrewai/output_schema.rb', line 73 def raise_unless(condition, ) raise OutputSchemaError, unless condition end |
.validate!(data, schema) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/rcrewai/output_schema.rb', line 43 def validate!(data, schema) type = (schema[:type] || schema['type'])&.to_s case type when 'object' then validate_object!(data, schema) when 'array' then raise_unless(data.is_a?(Array), 'expected an array') when 'string' then raise_unless(data.is_a?(String), 'expected a string') when 'integer' then raise_unless(data.is_a?(Integer), 'expected an integer') when 'number' then raise_unless(data.is_a?(Numeric), 'expected a number') when 'boolean' then raise_unless([true, false].include?(data), 'expected a boolean') end data end |
.validate_object!(data, schema) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/rcrewai/output_schema.rb', line 56 def validate_object!(data, schema) raise_unless(data.is_a?(Hash), 'expected a JSON object') required = schema[:required] || schema['required'] || [] required.each do |key| raise_unless(data.key?(key.to_s), "missing required property '#{key}'") end props = schema[:properties] || schema['properties'] || {} props.each do |name, subschema| value = data[name.to_s] next if value.nil? validate!(value, subschema) end end |