Class: Omakase::Schema

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

Overview

The declared return type, enforced by the provider. A schema whose only property is result unwraps to that value.

Constant Summary collapse

RESULT =
:result
SCALARS =
%i[string integer number boolean].freeze
RUBY_TYPES =
{
  "string" => String, "integer" => Integer, "number" => Numeric,
  "array" => Array, "object" => Hash
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(definition) ⇒ Schema

Returns a new instance of Schema.



26
27
28
# File 'lib/omakase/schema.rb', line 26

def initialize(definition)
  @definition = definition
end

Instance Attribute Details

#definitionObject (readonly)

Returns the value of attribute definition.



24
25
26
# File 'lib/omakase/schema.rb', line 24

def definition
  @definition
end

Class Method Details

.define(returns: nil, &block) ⇒ Object

Raises:



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

def self.define(returns: nil, &block)
  return new(Schematist::Schema.create(&block)) if block
  return Type.new(returns) if returns.is_a?(Module)

  type = returns || :string
  raise Error, "returns: must be one of #{SCALARS.join(", ")}, a class, or a block" unless SCALARS.include?(type)

  new(Schematist::Schema.create { public_send(type, RESULT) })
end

Instance Method Details

#cast(content) ⇒ Object

From the provider's JSON: unwrap first, then hold it to the contract.

Raises:



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

def cast(content)
  raise ContractError, "expected JSON matching #{JSON.generate(json)}, got #{content.inspect}" unless content.is_a?(Hash)

  data = RubyLLM::Utils.deep_symbolize_keys(content)
  take(wrapped? ? data.fetch(RESULT) { raise ContractError, %(missing "result" in #{data.inspect}) } : data)
end

#describeObject

The shape, in the shorthand the model writes back: {city: <string>}.



33
34
35
36
37
# File 'lib/omakase/schema.rb', line 33

def describe
  return "<#{properties.fetch("result")["type"]}>" if wrapped?

  "{#{properties.map { |name, spec| "#{name}: <#{spec["type"]}>" }.join(", ")}}"
end

#jsonObject



30
# File 'lib/omakase/schema.rb', line 30

def json = @json ||= definition.new.to_json_schema

#take(value) ⇒ Object

From a Ruby value the generated code computed.

Raises:



48
49
50
51
52
53
54
55
56
57
# File 'lib/omakase/schema.rb', line 48

def take(value)
  return demand(value, properties.fetch("result")["type"]) if wrapped?
  raise ContractError, "expected #{describe}, got #{value.inspect}" unless value.is_a?(Hash)

  data = RubyLLM::Utils.deep_symbolize_keys(value)
  missing = json.fetch("required").map(&:to_sym) - data.keys
  raise ContractError, "missing #{missing.join(", ")} — expected #{describe}" if missing.any?

  data
end

#wrapped?Boolean

Returns:

  • (Boolean)


59
# File 'lib/omakase/schema.rb', line 59

def wrapped? = definition.properties.keys == [RESULT]