11# frozen_string_literal: true
22
3+ require_relative "dsl/schema_builders"
4+ require_relative "dsl/primitive_types"
5+ require_relative "dsl/complex_types"
6+ require_relative "dsl/utilities"
7+
38module RubyLLM
49 class Schema
510 module DSL
6- # Primitive type methods
7- def string ( name = nil , enum : nil , description : nil , required : true , min_length : nil , max_length : nil , pattern : nil , format : nil )
8- options = {
9- enum : enum ,
10- description : description ,
11- minLength : min_length ,
12- maxLength : max_length ,
13- pattern : pattern ,
14- format : format
15- } . compact
16-
17- add_property ( name , build_property_schema ( :string , **options ) , required : required )
18- end
19-
20- def number ( name = nil , description : nil , required : true , minimum : nil , maximum : nil , multiple_of : nil )
21- options = {
22- description : description ,
23- minimum : minimum ,
24- maximum : maximum ,
25- multipleOf : multiple_of
26- } . compact
27-
28- add_property ( name , build_property_schema ( :number , **options ) , required : required )
29- end
30-
31- def integer ( name = nil , description : nil , required : true )
32- add_property ( name , build_property_schema ( :integer , description : description ) , required : required )
33- end
34-
35- def boolean ( name = nil , description : nil , required : true )
36- add_property ( name , build_property_schema ( :boolean , description : description ) , required : required )
37- end
38-
39- def null ( name = nil , description : nil , required : true )
40- add_property ( name , build_property_schema ( :null , description : description ) , required : required )
41- end
42-
43- # Complex type methods
44- def object ( name = nil , reference : nil , description : nil , required : true , &block )
45- add_property ( name , build_property_schema ( :object , description : description , reference : reference , &block ) , required : required )
46- end
47-
48- def array ( name , of : nil , description : nil , required : true , min_items : nil , max_items : nil , &block )
49- items = determine_array_items ( of , &block )
50-
51- add_property ( name , {
52- type : "array" ,
53- description : description ,
54- items : items ,
55- minItems : min_items ,
56- maxItems : max_items
57- } . compact , required : required )
58- end
59-
60- def any_of ( name = nil , required : true , description : nil , &block )
61- schemas = collect_property_schemas_from_block ( &block )
62-
63- add_property ( name , {
64- description : description ,
65- anyOf : schemas
66- } . compact , required : required )
67- end
68-
69- def optional ( name , description : nil , &block )
70- any_of ( name , description : description ) do
71- instance_eval ( &block )
72- null
73- end
74- end
75-
76- # Schema definition and reference methods
77- def define ( name , &)
78- sub_schema = Class . new ( Schema )
79- sub_schema . class_eval ( &)
80-
81- definitions [ name ] = {
82- type : "object" ,
83- properties : sub_schema . properties ,
84- required : sub_schema . required_properties ,
85- additionalProperties : sub_schema . additional_properties
86- }
87- end
88-
89- def reference ( schema_name )
90- if schema_name == :root
91- { "$ref" => "#" }
92- else
93- { "$ref" => "#/$defs/#{ schema_name } " }
94- end
95- end
96-
97- # Schema building methods
98- def build_property_schema ( type , **options , &)
99- case type
100- when :string
101- {
102- type : "string" ,
103- enum : options [ :enum ] ,
104- description : options [ :description ] ,
105- minLength : options [ :minLength ] ,
106- maxLength : options [ :maxLength ] ,
107- pattern : options [ :pattern ] ,
108- format : options [ :format ]
109- } . compact
110- when :number
111- {
112- type : "number" ,
113- description : options [ :description ] ,
114- minimum : options [ :minimum ] ,
115- maximum : options [ :maximum ] ,
116- multipleOf : options [ :multipleOf ]
117- } . compact
118- when :integer
119- {
120- type : "integer" ,
121- description : options [ :description ] ,
122- minimum : options [ :minimum ] ,
123- maximum : options [ :maximum ] ,
124- multipleOf : options [ :multipleOf ]
125- } . compact
126- when :boolean
127- { type : "boolean" , description : options [ :description ] } . compact
128- when :null
129- { type : "null" , description : options [ :description ] } . compact
130- when :object
131- # If the reference option is provided, return the reference
132- return reference ( options [ :reference ] ) if options [ :reference ]
133-
134- sub_schema = Class . new ( Schema )
135-
136- # Evaluate the block and capture the result
137- result = sub_schema . class_eval ( &)
138-
139- # If the block returned a reference and no properties were added, use the reference
140- if result . is_a? ( Hash ) && result [ "$ref" ] && sub_schema . properties . empty?
141- result . merge ( options [ :description ] ? { description : options [ :description ] } : { } )
142- else
143- {
144- type : "object" ,
145- properties : sub_schema . properties ,
146- required : sub_schema . required_properties ,
147- additionalProperties : sub_schema . additional_properties ,
148- description : options [ :description ]
149- } . compact
150- end
151- when :any_of
152- schemas = collect_property_schemas_from_block ( &)
153- {
154- anyOf : schemas
155- } . compact
156- else
157- raise InvalidSchemaTypeError , type
158- end
159- end
160-
161- private
162-
163- def add_property ( name , definition , required :)
164- properties [ name . to_sym ] = definition
165- required_properties << name . to_sym if required
166- end
167-
168- def determine_array_items ( of , &)
169- return collect_property_schemas_from_block ( &) . first if block_given?
170- return build_property_schema ( of ) if primitive_type? ( of )
171- return reference ( of ) if of . is_a? ( Symbol )
172-
173- raise InvalidArrayTypeError , of
174- end
175-
176- def collect_property_schemas_from_block ( &block )
177- schemas = [ ]
178- schema_builder = self # Capture the current context that has build_property_schema
179-
180- context = Object . new
181- context . define_singleton_method ( :string ) { |name = nil , **options | schemas << schema_builder . build_property_schema ( :string , **options ) }
182- context . define_singleton_method ( :number ) { |name = nil , **options | schemas << schema_builder . build_property_schema ( :number , **options ) }
183- context . define_singleton_method ( :integer ) { |name = nil , **options | schemas << schema_builder . build_property_schema ( :integer , **options ) }
184- context . define_singleton_method ( :boolean ) { |name = nil , **options | schemas << schema_builder . build_property_schema ( :boolean , **options ) }
185- context . define_singleton_method ( :null ) { |name = nil , **options | schemas << schema_builder . build_property_schema ( :null , **options ) }
186- context . define_singleton_method ( :object ) { |name = nil , **options , &blk | schemas << schema_builder . build_property_schema ( :object , **options , &blk ) }
187- context . define_singleton_method ( :any_of ) { |name = nil , **options , &blk | schemas << schema_builder . build_property_schema ( :any_of , **options , &blk ) }
188-
189- context . instance_eval ( &block )
190- schemas
191- end
192-
193- def primitive_type? ( type )
194- type . is_a? ( Symbol ) && PRIMITIVE_TYPES . include? ( type )
195- end
11+ include SchemaBuilders
12+ include PrimitiveTypes
13+ include ComplexTypes
14+ include Utilities
19615 end
19716 end
198- end
17+ end
0 commit comments