Class: ActiveAgent::Delegation::Schema
- Inherits:
-
Object
- Object
- ActiveAgent::Delegation::Schema
- Defined in:
- lib/active_agent/delegation/schema.rb
Overview
Declarative JSON Schema for a delegated agent's inputs and outputs.
A delegation is only as good as its contract: the calling model needs to
know exactly what a sub-agent accepts, and the calling agent needs to
know what shape comes back. Schema builds both from a small DSL, from a
plain JSON Schema hash, or from any class that responds to
to_json_schema (see SchemaGenerator).
Constant Summary collapse
- SCALAR_TYPES =
Scalar types that get a one-line DSL helper.
%i[string integer number boolean].freeze
Class Method Summary collapse
-
.build(source = nil) { ... } ⇒ Schema
Coerces any supported schema source into a Schema.
- .from_hash(hash) ⇒ Schema
Instance Method Summary collapse
- #additional_properties(value = true) ⇒ Object
-
#array(name, of: nil, **options) { ... } ⇒ Object
Declares an array property.
-
#empty? ⇒ Boolean
True when nothing has been declared.
-
#initialize ⇒ Schema
constructor
A new instance of Schema.
-
#keys ⇒ Array<Symbol>
Declared property names.
-
#missing_keys(payload) ⇒ Array<Symbol>
Validates a parsed payload against the declared required properties.
-
#object(name, **options) { ... } ⇒ Object
Declares an object property.
-
#param(name, type = :string, required: false, description: nil, **options) { ... } ⇒ void
Declares a property.
-
#property(name, definition) ⇒ void
Declares a property from an already-built JSON Schema fragment.
-
#required(*names) ⇒ Array<Symbol>
Marks properties as required.
-
#required_keys ⇒ Array<Symbol>
Required property names.
-
#to_json_schema ⇒ Hash
(also: #to_h)
JSON Schema object.
-
#to_response_format(name:, strict: true) ⇒ Hash
JSON Schema for a
response_formatpayload.
Constructor Details
#initialize ⇒ Schema
Returns a new instance of Schema.
72 73 74 75 76 |
# File 'lib/active_agent/delegation/schema.rb', line 72 def initialize @properties = {} @required = [] @additional_properties = false end |
Class Method Details
.build(source = nil) { ... } ⇒ Schema
Coerces any supported schema source into a Schema.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/active_agent/delegation/schema.rb', line 37 def build(source = nil, &block) schema = case source when Schema then source when Hash then from_hash(source) when nil then new else if source.respond_to?(:to_json_schema) from_hash(source.to_json_schema) else raise ArgumentError, "Cannot build a delegation schema from #{source.inspect}. " \ "Pass a Hash, a class responding to #to_json_schema, or use the block DSL." end end if block block.arity == 1 ? block.call(schema) : schema.instance_eval(&block) end schema end |
.from_hash(hash) ⇒ Schema
61 62 63 64 65 66 67 68 69 |
# File 'lib/active_agent/delegation/schema.rb', line 61 def from_hash(hash) hash = hash.deep_symbolize_keys new.tap do |schema| (hash[:properties] || {}).each { |name, definition| schema.property(name, definition) } schema.required(*Array(hash[:required])) schema.additional_properties(hash.fetch(:additionalProperties, hash.fetch(:additional_properties, false))) end end |
Instance Method Details
#additional_properties(value = true) ⇒ Object
157 158 159 |
# File 'lib/active_agent/delegation/schema.rb', line 157 def additional_properties(value = true) @additional_properties = value end |
#array(name, of: nil, **options) { ... } ⇒ Object
Declares an array property.
134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/active_agent/delegation/schema.rb', line 134 def array(name, of: nil, **, &block) items = if block self.class.build(&block).to_json_schema elsif of.is_a?(Hash) of.deep_symbolize_keys elsif of { type: of.to_s } end param(name, :array, **.merge({ items: items }.compact)) end |
#empty? ⇒ Boolean
Returns true when nothing has been declared.
79 80 81 |
# File 'lib/active_agent/delegation/schema.rb', line 79 def empty? @properties.empty? end |
#keys ⇒ Array<Symbol>
Returns declared property names.
162 163 164 |
# File 'lib/active_agent/delegation/schema.rb', line 162 def keys @properties.keys end |
#missing_keys(payload) ⇒ Array<Symbol>
Validates a parsed payload against the declared required properties.
This is a deliberately shallow check: it catches the failure that actually happens in practice (a model omitting a required key) without pulling a full JSON Schema validator into the gem's dependencies.
211 212 213 214 215 216 217 |
# File 'lib/active_agent/delegation/schema.rb', line 211 def missing_keys(payload) return required_keys if payload.nil? return [] unless payload.is_a?(Hash) keys = payload.keys.map { |key| key.to_s.underscore.to_sym } required_keys.reject { |key| keys.include?(key) } end |
#object(name, **options) { ... } ⇒ Object
Declares an object property.
125 126 127 |
# File 'lib/active_agent/delegation/schema.rb', line 125 def object(name, **, &block) param(name, :object, **, &block) end |
#param(name, type = :string, required: false, description: nil, **options) { ... } ⇒ void
This method returns an undefined value.
Declares a property.
102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/active_agent/delegation/schema.rb', line 102 def param(name, type = :string, required: false, description: nil, **, &block) definition = { type: type.to_s, description: description }.compact.merge() if block nested = self.class.build(&block) definition = definition.merge(nested.to_json_schema.except(:type)) definition[:type] = "object" end property(name, definition) self.required(name) if required end |
#property(name, definition) ⇒ void
This method returns an undefined value.
Declares a property from an already-built JSON Schema fragment.
88 89 90 |
# File 'lib/active_agent/delegation/schema.rb', line 88 def property(name, definition) @properties[name.to_sym] = definition.deep_symbolize_keys end |
#required(*names) ⇒ Array<Symbol>
Marks properties as required.
151 152 153 154 |
# File 'lib/active_agent/delegation/schema.rb', line 151 def required(*names) names.flatten.each { |name| @required |= [ name.to_sym ] } @required end |
#required_keys ⇒ Array<Symbol>
Returns required property names.
167 168 169 |
# File 'lib/active_agent/delegation/schema.rb', line 167 def required_keys @required.dup end |
#to_json_schema ⇒ Hash Also known as: to_h
Deep-duplicated: providers normalize tool definitions in place, and a schema is shared by every generation that exposes it.
Returns JSON Schema object.
175 176 177 178 179 180 181 182 |
# File 'lib/active_agent/delegation/schema.rb', line 175 def to_json_schema { type: "object", properties: @properties.deep_dup, required: @required.map(&:to_s), additionalProperties: @additional_properties } end |
#to_response_format(name:, strict: true) ⇒ Hash
JSON Schema for a response_format payload.
ActiveAgent camelizes response-format schema keys on the way to the
provider, but the required array holds string values — so they are
camelized here to keep the emitted schema internally consistent.
Assistant#parsed_json underscores the keys again on the way back, so
agent code only ever sees snake_case.
196 197 198 199 200 201 |
# File 'lib/active_agent/delegation/schema.rb', line 196 def to_response_format(name:, strict: true) schema = to_json_schema schema[:required] = schema[:required].map { |key| key.camelize(:lower) } { name: name, schema: schema, strict: strict } end |