Class: OpenRouter::Schema

Inherits:
Object
  • Object
show all
Defined in:
lib/open_router/schema.rb

Defined Under Namespace

Classes: ItemsBuilder, SchemaBuilder

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, schema_definition = {}, strict: true) ⇒ Schema

Returns a new instance of Schema.

Raises:

  • (ArgumentError)


15
16
17
18
19
20
21
22
# File 'lib/open_router/schema.rb', line 15

def initialize(name, schema_definition = {}, strict: true)
  @name = name
  @strict = strict
  raise ArgumentError, "Schema definition must be a hash" unless schema_definition.is_a?(Hash)

  @schema = schema_definition
  validate_schema!
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



13
14
15
# File 'lib/open_router/schema.rb', line 13

def name
  @name
end

#schemaObject (readonly)

Returns the value of attribute schema.



13
14
15
# File 'lib/open_router/schema.rb', line 13

def schema
  @schema
end

#strictObject (readonly)

Returns the value of attribute strict.



13
14
15
# File 'lib/open_router/schema.rb', line 13

def strict
  @strict
end

Class Method Details

.define(name, strict: true, &block) ⇒ Object

Class method for defining schemas with a DSL



25
26
27
28
29
# File 'lib/open_router/schema.rb', line 25

def self.define(name, strict: true, &block)
  builder = SchemaBuilder.new
  builder.instance_eval(&block) if block_given?
  new(name, builder.to_h, strict:)
end

Instance Method Details

#get_format_instructions(forced: false) ⇒ Object

Generate format instructions for model prompting



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/open_router/schema.rb', line 93

def get_format_instructions(forced: false)
  schema_json = to_h.to_json

  if forced
    <<~INSTRUCTIONS
      You must format your output as a JSON value that conforms exactly to the following JSON Schema specification:

      #{schema_json}

      CRITICAL: Your entire response must be valid JSON that matches this schema. Do not include any text before or after the JSON. Return ONLY the JSON value itself - no other text, explanations, or formatting.

      example format:
      ```json
      {"field1": "value1", "field2": "value2"}
      ```

      Important guidelines:
      - Ensure all required fields match the schema exactly
      - Use proper JSON formatting (no trailing commas)
      - All string values must be properly quoted
    INSTRUCTIONS
  else
    <<~INSTRUCTIONS
      Please format your output as a JSON value that conforms to the following JSON Schema specification:

      #{schema_json}

      Your response should be valid JSON that matches this schema structure exactly.

      example format:
      ```json
      {"field1": "value1", "field2": "value2"}
      ```

      Important guidelines:
      - Ensure all required fields match the schema
      - Use proper JSON formatting (no trailing commas)
      - Return ONLY the JSON - no other text or explanations
    INSTRUCTIONS
  end
end

#pure_schemaObject

Get the pure JSON Schema (respects required flags) for testing/validation



65
66
67
# File 'lib/open_router/schema.rb', line 65

def pure_schema
  @schema
end

#to_hObject

Convert to the format expected by OpenRouter API.

This is the honest representation: it respects the required arrays exactly as declared, so fields you left optional stay optional. It is what we describe to the model (prompt injection), what we validate against, and what we hand the healer — keeping "what we ask for" and "what we accept" in agreement. The provider-strict, all-required form lives in #to_strict_h and is used only when serializing a native json_schema request.



39
40
41
42
43
44
45
# File 'lib/open_router/schema.rb', line 39

def to_h
  {
    name: @name,
    strict: @strict,
    schema: @schema
  }
end

#to_json(*args) ⇒ Object



69
70
71
# File 'lib/open_router/schema.rb', line 69

def to_json(*args)
  to_h.to_json(*args)
end

#to_strict_hObject

Provider-strict form for native json_schema decoding.

OpenRouter / OpenAI strict mode requires EVERY object — at every nesting level, including nested objects and array items — to list all of its properties in its required array; a nested required: [] gets a 400. We satisfy that WITHOUT silently making optional fields mandatory: any property that was not declared required is made nullable (its type gains "null"), which is exactly how strict mode expresses optionality. The model may then return null for it instead of being forced to invent a value.



56
57
58
59
60
61
62
# File 'lib/open_router/schema.rb', line 56

def to_strict_h
  {
    name: @name,
    strict: @strict,
    schema: enforce_all_required(@schema)
  }
end

#validate(data) ⇒ Object

Validate data against this schema



79
80
81
82
83
# File 'lib/open_router/schema.rb', line 79

def validate(data)
  return true unless defined?(JSON::Validator)

  JSON::Validator.validate(@schema, data)
end

#validation_available?Boolean

Check if JSON schema validation is available

Returns:

  • (Boolean)


74
75
76
# File 'lib/open_router/schema.rb', line 74

def validation_available?
  !!defined?(JSON::Validator)
end

#validation_errors(data) ⇒ Object

Get validation errors for data



86
87
88
89
90
# File 'lib/open_router/schema.rb', line 86

def validation_errors(data)
  return [] unless defined?(JSON::Validator)

  JSON::Validator.fully_validate(@schema, data)
end