Class: Pikuri::Tool::Parameters
- Inherits:
-
Object
- Object
- Pikuri::Tool::Parameters
- Defined in:
- lib/pikuri/tool/parameters.rb
Overview
Schema for a Pikuri::Tool‘s arguments. Built up via the fluent <required|optional>_<type> methods, then frozen by Parameters.build; serializes to the OpenAI JSON-Schema shape via #to_h and validates LLM-supplied argument hashes via #validate.
Defined Under Namespace
Classes: ValidationError
Class Method Summary collapse
-
.build {|builder| ... } ⇒ Parameters
Yield a fresh builder, freeze it, and return it.
Instance Method Summary collapse
-
#freeze ⇒ self
Freeze the builder along with its internal collections, so post-build mutation attempts raise
FrozenErrorinstead of silently succeeding. - #initialize ⇒ Parameters constructor
-
#optional_boolean(name, description) ⇒ self
Add an optional
booleanproperty. -
#optional_integer(name, description) ⇒ self
Add an optional
integerproperty. -
#optional_number(name, description) ⇒ self
Add an optional
numberproperty. -
#optional_string(name, description) ⇒ self
Add an optional
stringproperty. -
#required_boolean(name, description) ⇒ self
Add a required
booleanproperty. -
#required_integer(name, description) ⇒ self
Add a required
integerproperty. -
#required_number(name, description) ⇒ self
Add a required
numberproperty (JSON-Schemanumber: Integer or finite Float). -
#required_string(name, description) ⇒ self
Add a required
stringproperty. -
#to_h ⇒ Hash
Schema in OpenAI JSON-Schema shape.
-
#validate(args) ⇒ Hash{Symbol=>Object}
Validate a tool-call argument hash against the declared schema.
Constructor Details
#initialize ⇒ Parameters
38 39 40 41 |
# File 'lib/pikuri/tool/parameters.rb', line 38 def initialize @properties = {} @required = [] end |
Class Method Details
.build {|builder| ... } ⇒ Parameters
Yield a fresh builder, freeze it, and return it.
31 32 33 34 35 |
# File 'lib/pikuri/tool/parameters.rb', line 31 def self.build builder = new yield builder builder.freeze end |
Instance Method Details
#freeze ⇒ self
Freeze the builder along with its internal collections, so post-build mutation attempts raise FrozenError instead of silently succeeding.
47 48 49 50 51 |
# File 'lib/pikuri/tool/parameters.rb', line 47 def freeze @properties.freeze @required.freeze super end |
#optional_boolean(name, description) ⇒ self
Add an optional boolean property. See #required_boolean for accepted shapes.
132 133 134 |
# File 'lib/pikuri/tool/parameters.rb', line 132 def optional_boolean(name, description) add(name, 'boolean', description, required: false) end |
#optional_integer(name, description) ⇒ self
Add an optional integer property. See #required_integer for accepted shapes.
88 89 90 |
# File 'lib/pikuri/tool/parameters.rb', line 88 def optional_integer(name, description) add(name, 'integer', description, required: false) end |
#optional_number(name, description) ⇒ self
Add an optional number property. See #required_number for accepted shapes.
109 110 111 |
# File 'lib/pikuri/tool/parameters.rb', line 109 def optional_number(name, description) add(name, 'number', description, required: false) end |
#optional_string(name, description) ⇒ self
Add an optional string property.
67 68 69 |
# File 'lib/pikuri/tool/parameters.rb', line 67 def optional_string(name, description) add(name, 'string', description, required: false) end |
#required_boolean(name, description) ⇒ self
Add a required boolean property. Accepts Ruby true/false as-is, and the literal Strings “true”/“false” (some models surface JSON booleans as Strings) after trimming surrounding whitespace. Other Strings, numbers, and nil are rejected —there is no truthy-coercion of “yes” / 0 / etc.
122 123 124 |
# File 'lib/pikuri/tool/parameters.rb', line 122 def required_boolean(name, description) add(name, 'boolean', description, required: true) end |
#required_integer(name, description) ⇒ self
Add a required integer property. Accepts Integers, Floats with a zero fractional part (e.g. 1.0), and base-10 numeric Strings (after trimming) that resolve to whole numbers; rejects everything else.
78 79 80 |
# File 'lib/pikuri/tool/parameters.rb', line 78 def required_integer(name, description) add(name, 'integer', description, required: true) end |
#required_number(name, description) ⇒ self
Add a required number property (JSON-Schema number: Integer or finite Float). Numeric Strings (after trimming) are parsed; NaN and Infinity are rejected.
99 100 101 |
# File 'lib/pikuri/tool/parameters.rb', line 99 def required_number(name, description) add(name, 'number', description, required: true) end |
#required_string(name, description) ⇒ self
Add a required string property.
58 59 60 |
# File 'lib/pikuri/tool/parameters.rb', line 58 def required_string(name, description) add(name, 'string', description, required: true) end |
#to_h ⇒ Hash
Schema in OpenAI JSON-Schema shape.
139 140 141 |
# File 'lib/pikuri/tool/parameters.rb', line 139 def to_h { type: 'object', properties: @properties, required: @required } end |
#validate(args) ⇒ Hash{Symbol=>Object}
Validate a tool-call argument hash against the declared schema. Returns a symbol-keyed hash safe to splat as kwargs into a tool’s execute Proc; raises ValidationError with an LLM-actionable message listing every missing/unknown/mistyped field and reprinting the schema.
Strict: unknown keys are rejected (with DidYouMean suggestions), wrong types are rejected. All issues are collected and reported together so the LLM can fix them in one round trip.
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/pikuri/tool/parameters.rb', line 157 def validate(args) raise ValidationError, "Arguments must be an object, got #{args.class}." unless args.is_a?(Hash) symbolized = args.transform_keys(&:to_sym) errors = [] result = {} (symbolized.keys - @properties.keys).each do |unknown| errors << unknown_key_error(unknown) end @properties.each do |name, schema| if symbolized.key?(name) begin result[name] = coerce(symbolized[name], schema[:type]) rescue CoercionError => e errors << "Parameter `#{name}` #{e.}." end elsif @required.include?(name.to_s) errors << "Missing required parameter `#{name}` (#{schema[:type]}): #{schema[:description]}" end end return result if errors.empty? raise ValidationError, (errors) end |