ruby_llm-schema 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af385c490955340f248b031be93c2f3667b8bb3163b705469d0cfce7d18e428f
4
- data.tar.gz: 3636b4f7d55eabf5399396f8a708d26d611f2afb6bd9677bb6a1a189b9fe03ef
3
+ metadata.gz: 4706281dcd180f4d6e2b385cc42b79d73629d8eb8a7b5723ddde3b2786a5022e
4
+ data.tar.gz: eb083d6fa029a0b107f7a728c86e9f8342a1b9d0c3d0a46d8d4d33adaacd756a
5
5
  SHA512:
6
- metadata.gz: 9db25536a6c7f3cb32a6cba0e91d88665833f25e6ea51f630be4ea18aa8d50ab7809e13e31d3dce4f0cd757be36754dca6fd3063832a6dd9a91129c07903087d
7
- data.tar.gz: 486daf28cc008eda346b7c4c1b33f5723fac2f50947ae8197fba8fa6a23d9f50921a36533c37f60942cde6b5f030260045a779066546581d67b209fd76867818
6
+ metadata.gz: bc52ea4b47664561909278ece104676ae5053572aa791fe6985deb1ecdf40421e49b3b02529ba2a02cbb1df068484d6d162ec0d4c8d525105111ced98451fcbf
7
+ data.tar.gz: df555cdab1fb1c786ee0425fb5a1c0dd61bd5ed6c35dfc53bb355cdad27b462c5dbd84cb5d8fb32db6fdbe2c364916f0c8d2ed32565bff87c8ca17b79915ee03
data/README.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  A Ruby DSL for creating JSON schemas with a clean, Rails-inspired API. Perfect for defining structured data schemas for LLM function calling or structured outputs.
4
4
 
5
+ ## Use Cases
6
+
7
+ Structured output is a powerful tool for LLMs to generate consistent and predictable responses.
8
+
9
+ Some ideal use cases:
10
+
11
+ - Extracting *metadata, topics, and summary* from articles or blog posts
12
+ - Organizing unstructured feedback or reviews with *sentiment and summary*
13
+ - Defining structured *actions* from user messages or emails
14
+ - Extracting *entities and relationships* from documents
15
+
5
16
  ### Simple Example
6
17
 
7
18
  ```ruby
@@ -122,29 +133,83 @@ end
122
133
  puts person_schema.to_json
123
134
  ```
124
135
 
125
- ## Field Types
136
+ ## Schema Property Types
137
+
138
+ A schema is a collection of properties, which can be of different types. Each type has its own set of properties you can set.
139
+
140
+ All property types can (along with the required `name` key) be set with a `description` and a `required` flag (default is `true`).
141
+
142
+ ```ruby
143
+ string :name, description: "Person's full name"
144
+ number :age, description: "Person's age", required: false
145
+ boolean :is_active, description: "Whether the person is active"
146
+ null :placeholder, description: "A placeholder property"
147
+ ```
148
+
149
+ ⚠️ Please consult the LLM provider documentation for any limitations or restrictions. For example, as of now, OpenAI requires all properties to be required. In that case, you can use the `any_of` method to make a property optional.
150
+
151
+ ```ruby
152
+ any_of :name, description: "Person's full name" do
153
+ string
154
+ null
155
+ end
156
+ ```
157
+
158
+ ### Strings
159
+
160
+ String types support the following properties:
161
+
162
+ - `enum`: an array of allowed values (e.g. `enum: ["on", "off"]`)
163
+ - `pattern`: a regex pattern (e.g. `pattern: "\\d+"`)
164
+ - `format`: a format string (e.g. `format: "email"`)
165
+ - `min_length`: the minimum length of the string (e.g. `min_length: 3`)
166
+ - `max_length`: the maximum length of the string (e.g. `max_length: 10`)
167
+
168
+ Please consult the LLM provider documentation for the available formats and patterns.
169
+
170
+ ```ruby
171
+ string :name, description: "Person's full name"
172
+ string :email, format: "email"
173
+ string :phone, pattern: "\\d+"
174
+ string :status, enum: ["on", "off"]
175
+ string :code, min_length: 3, max_length: 10
176
+ ```
177
+
178
+ ### Numbers
126
179
 
127
- ### Primitive Types
180
+ Number types support the following properties:
181
+
182
+ - `multiple_of`: a multiple of the number (e.g. `multiple_of: 0.01`)
183
+ - `minimum`: the minimum value of the number (e.g. `minimum: 0`)
184
+ - `maximum`: the maximum value of the number (e.g. `maximum: 100`)
128
185
 
129
186
  ```ruby
130
- string :name # Required string
131
- string :title, required: false # Optional string
132
- string :status, enum: ["on", "off"] # String with enum values
133
- string :email, format: "email" # String with format validation
134
- string :code, min_length: 3, max_length: 10 # String with length constraints
135
- string :pattern_field, pattern: "\\d+" # String with regex pattern
187
+ number :price, minimum: 0, maximum: 100
188
+ number :amount, multiple_of: 0.01
189
+ ```
136
190
 
137
- number :count # Required number
138
- number :price, minimum: 0, maximum: 100 # Number with range constraints
139
- number :amount, multiple_of: 0.01 # Number with precision constraints
191
+ ### Booleans
140
192
 
141
- integer :id # Required integer
142
- boolean :active # Required boolean
143
- null :placeholder # Null type
193
+ ```ruby
194
+ boolean :is_active
144
195
  ```
145
196
 
197
+ Boolean types doesn't support any additional properties.
198
+
199
+ ### Null
200
+
201
+ ```ruby
202
+ null :placeholder
203
+ ```
204
+
205
+ Null types doesn't support any additional properties.
206
+
146
207
  ### Arrays
147
208
 
209
+ An array is a list of items. You can set the type of the items in the array with the `of` option or by passing a block with the `object` method.
210
+
211
+ An array can have a `min_items` and `max_items` option to set the minimum and maximum number of items in the array.
212
+
148
213
  ```ruby
149
214
  array :tags, of: :string # Array of strings
150
215
  array :scores, of: :number # Array of numbers
@@ -160,6 +225,8 @@ end
160
225
 
161
226
  ### Objects
162
227
 
228
+ Objects types expect a block with the properties of the object.
229
+
163
230
  ```ruby
164
231
  object :user do
165
232
  string :name
@@ -174,6 +241,8 @@ end
174
241
 
175
242
  ### Union Types (anyOf)
176
243
 
244
+ Union types are a way to specify that a property can be one of several types.
245
+
177
246
  ```ruby
178
247
  any_of :value do
179
248
  string
@@ -189,6 +258,8 @@ end
189
258
 
190
259
  ### Schema Definitions and References
191
260
 
261
+ You can define sub-schemas and reference them in other schemas.
262
+
192
263
  ```ruby
193
264
  class MySchema < RubyLLM::Schema
194
265
  define :location do
data/Rakefile CHANGED
@@ -3,3 +3,10 @@
3
3
  require "bundler/gem_tasks"
4
4
  require "rspec/core/rake_task"
5
5
  require "standard/rake"
6
+
7
+ # Load custom tasks
8
+ Dir.glob("lib/tasks/**/*.rake").each { |r| load r }
9
+
10
+ RSpec::Core::RakeTask.new(:spec)
11
+
12
+ task default: %i[standard spec]
@@ -0,0 +1,183 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ class Schema
5
+ 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, description: nil, required: true, &block)
45
+ add_property(name, build_property_schema(:object, description: description, &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
+ }
86
+ end
87
+
88
+ def reference(schema_name)
89
+ {"$ref" => "#/$defs/#{schema_name}"}
90
+ end
91
+
92
+ # Schema building methods
93
+ def build_property_schema(type, **options, &)
94
+ case type
95
+ when :string
96
+ {
97
+ type: "string",
98
+ enum: options[:enum],
99
+ description: options[:description],
100
+ minLength: options[:minLength],
101
+ maxLength: options[:maxLength],
102
+ pattern: options[:pattern],
103
+ format: options[:format]
104
+ }.compact
105
+ when :number
106
+ {
107
+ type: "number",
108
+ description: options[:description],
109
+ minimum: options[:minimum],
110
+ maximum: options[:maximum],
111
+ multipleOf: options[:multipleOf]
112
+ }.compact
113
+ when :integer
114
+ {
115
+ type: "integer",
116
+ description: options[:description],
117
+ minimum: options[:minimum],
118
+ maximum: options[:maximum],
119
+ multipleOf: options[:multipleOf]
120
+ }.compact
121
+ when :boolean
122
+ {type: "boolean", description: options[:description]}.compact
123
+ when :null
124
+ {type: "null", description: options[:description]}.compact
125
+ when :object
126
+ sub_schema = Class.new(Schema)
127
+ sub_schema.class_eval(&)
128
+
129
+ {
130
+ type: "object",
131
+ properties: sub_schema.properties,
132
+ required: sub_schema.required_properties,
133
+ additionalProperties: additional_properties,
134
+ description: options[:description]
135
+ }.compact
136
+ when :any_of
137
+ schemas = collect_property_schemas_from_block(&)
138
+ {
139
+ anyOf: schemas
140
+ }.compact
141
+ else
142
+ raise InvalidSchemaTypeError, type
143
+ end
144
+ end
145
+
146
+ private
147
+
148
+ def add_property(name, definition, required:)
149
+ properties[name.to_sym] = definition
150
+ required_properties << name.to_sym if required
151
+ end
152
+
153
+ def determine_array_items(of, &)
154
+ return collect_property_schemas_from_block(&).first if block_given?
155
+ return build_property_schema(of) if primitive_type?(of)
156
+ return reference(of) if of.is_a?(Symbol)
157
+
158
+ raise InvalidArrayTypeError, of
159
+ end
160
+
161
+ def collect_property_schemas_from_block(&block)
162
+ schemas = []
163
+ schema_builder = self # Capture the current context that has build_property_schema
164
+
165
+ context = Object.new
166
+ context.define_singleton_method(:string) { |name = nil, **options| schemas << schema_builder.build_property_schema(:string, **options) }
167
+ context.define_singleton_method(:number) { |name = nil, **options| schemas << schema_builder.build_property_schema(:number, **options) }
168
+ context.define_singleton_method(:integer) { |name = nil, **options| schemas << schema_builder.build_property_schema(:integer, **options) }
169
+ context.define_singleton_method(:boolean) { |name = nil, **options| schemas << schema_builder.build_property_schema(:boolean, **options) }
170
+ context.define_singleton_method(:null) { |name = nil, **options| schemas << schema_builder.build_property_schema(:null, **options) }
171
+ context.define_singleton_method(:object) { |name = nil, **options, &blk| schemas << schema_builder.build_property_schema(:object, **options, &blk) }
172
+ context.define_singleton_method(:any_of) { |name = nil, **options, &blk| schemas << schema_builder.build_property_schema(:any_of, **options, &blk) }
173
+
174
+ context.instance_eval(&block)
175
+ schemas
176
+ end
177
+
178
+ def primitive_type?(type)
179
+ type.is_a?(Symbol) && PRIMITIVE_TYPES.include?(type)
180
+ end
181
+ end
182
+ end
183
+ end
@@ -7,4 +7,4 @@ module RubyLLM
7
7
  schema_class.new(name, description: description)
8
8
  end
9
9
  end
10
- end
10
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ class Schema
5
+ module JsonOutput
6
+ def to_json_schema
7
+ validate! # Validate schema before generating JSON
8
+
9
+ {
10
+ name: @name,
11
+ description: @description || self.class.description,
12
+ schema: {
13
+ :type => "object",
14
+ :properties => self.class.properties,
15
+ :required => self.class.required_properties,
16
+ :additionalProperties => self.class.additional_properties,
17
+ :strict => self.class.strict,
18
+ "$defs" => self.class.definitions
19
+ }
20
+ }
21
+ end
22
+
23
+ def to_json(*_args)
24
+ validate! # Validate schema before generating JSON string
25
+ JSON.pretty_generate(to_json_schema)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -32,7 +32,7 @@ module RubyLLM
32
32
 
33
33
  # Initialize all nodes as WHITE (no mark)
34
34
  marks = Hash.new { WHITE }
35
-
35
+
36
36
  # Visit each unmarked node
37
37
  definitions.each_key do |node|
38
38
  visit(node, definitions, marks) if marks[node] == WHITE
@@ -43,7 +43,7 @@ module RubyLLM
43
43
  def visit(node, definitions, marks)
44
44
  # If node has a permanent mark, return
45
45
  return if marks[node] == BLACK
46
-
46
+
47
47
  # If node has a temporary mark, we found a cycle
48
48
  if marks[node] == GRAY
49
49
  raise ValidationError, "Circular reference detected involving '#{node}'"
@@ -51,7 +51,7 @@ module RubyLLM
51
51
 
52
52
  # Mark node with temporary mark
53
53
  marks[node] = GRAY
54
-
54
+
55
55
  # Visit all adjacent nodes (dependencies)
56
56
  definition = definitions[node]
57
57
  if definition && definition[:properties]
@@ -62,14 +62,14 @@ module RubyLLM
62
62
  end
63
63
  end
64
64
  end
65
-
65
+
66
66
  # Mark node with permanent mark
67
67
  marks[node] = BLACK
68
68
  end
69
69
 
70
70
  def extract_references(property)
71
71
  references = []
72
-
72
+
73
73
  case property
74
74
  when Hash
75
75
  if property["$ref"]
@@ -92,4 +92,4 @@ module RubyLLM
92
92
  end
93
93
  end
94
94
  end
95
- end
95
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RubyLlm
4
4
  class Schema
5
- VERSION = "0.1.5"
5
+ VERSION = "0.1.7"
6
6
  end
7
7
  end
@@ -1,15 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "schema/version"
4
- require_relative "schema/property_schema_collector"
5
4
  require_relative "schema/errors"
6
5
  require_relative "schema/helpers"
7
6
  require_relative "schema/validator"
7
+ require_relative "schema/dsl"
8
+ require_relative "schema/json_output"
8
9
  require "json"
9
- require "set"
10
10
 
11
11
  module RubyLLM
12
12
  class Schema
13
+ extend DSL
14
+ include JsonOutput
15
+
13
16
  PRIMITIVE_TYPES = %i[string number integer boolean null].freeze
14
17
 
15
18
  class << self
@@ -19,104 +22,6 @@ module RubyLLM
19
22
  schema_class
20
23
  end
21
24
 
22
- def description(description = nil)
23
- @description = description if description
24
- @description
25
- end
26
-
27
- def additional_properties(value = nil)
28
- return @additional_properties ||= false if value.nil?
29
- @additional_properties = value
30
- end
31
-
32
- def strict(value = nil)
33
- return @strict ||= true if value.nil?
34
- @strict = value
35
- end
36
-
37
- def string(name = nil, enum: nil, description: nil, required: true, min_length: nil, max_length: nil, pattern: nil, format: nil)
38
- options = {
39
- enum: enum,
40
- description: description,
41
- minLength: min_length,
42
- maxLength: max_length,
43
- pattern: pattern,
44
- format: format
45
- }.compact
46
-
47
- add_property(name, build_property_schema(:string, **options), required: required)
48
- end
49
-
50
- def number(name = nil, description: nil, required: true, minimum: nil, maximum: nil, multiple_of: nil)
51
- options = {
52
- description: description,
53
- minimum: minimum,
54
- maximum: maximum,
55
- multipleOf: multiple_of
56
- }.compact
57
-
58
- add_property(name, build_property_schema(:number, **options), required: required)
59
- end
60
-
61
- def integer(name = nil, description: nil, required: true)
62
- add_property(name, build_property_schema(:integer, description: description), required: required)
63
- end
64
-
65
- def boolean(name = nil, description: nil, required: true)
66
- add_property(name, build_property_schema(:boolean, description: description), required: required)
67
- end
68
-
69
- def null(name = nil, description: nil, required: true)
70
- add_property(name, build_property_schema(:null, description: description), required: required)
71
- end
72
-
73
- def object(name = nil, description: nil, required: true, &block)
74
- add_property(name, build_property_schema(:object, description: description, &block), required: required)
75
- end
76
-
77
- def array(name, of: nil, description: nil, required: true, min_items: nil, max_items: nil, &block)
78
- items = determine_array_items(of, &block)
79
-
80
- add_property(name, {
81
- type: "array",
82
- description: description,
83
- items: items,
84
- minItems: min_items,
85
- maxItems: max_items
86
- }.compact, required: required)
87
- end
88
-
89
- def any_of(name, required: true, description: nil, &block)
90
- schemas = collect_property_schemas_from_block(&block)
91
-
92
- add_property(name, {
93
- description: description,
94
- anyOf: schemas
95
- }.compact, required: required)
96
- end
97
-
98
- def optional(name, description: nil, &block)
99
- any_of(name, description: description) do
100
- instance_eval(&block)
101
- null
102
- end
103
- end
104
-
105
- def define(name, &)
106
- sub_schema = Class.new(Schema)
107
- sub_schema.class_eval(&)
108
-
109
- definitions[name] = {
110
- type: "object",
111
- properties: sub_schema.properties,
112
- required: sub_schema.required_properties
113
- }
114
- end
115
-
116
- def reference(schema_name)
117
- {"$ref" => "#/$defs/#{schema_name}"}
118
- end
119
-
120
25
  def properties
121
26
  @properties ||= {}
122
27
  end
@@ -129,52 +34,21 @@ module RubyLLM
129
34
  @definitions ||= {}
130
35
  end
131
36
 
132
- def build_property_schema(type, **options, &)
133
- case type
134
- when :string
135
- {
136
- type: "string",
137
- enum: options[:enum],
138
- description: options[:description],
139
- minLength: options[:minLength],
140
- maxLength: options[:maxLength],
141
- pattern: options[:pattern],
142
- format: options[:format]
143
- }.compact
144
- when :number
145
- {
146
- type: "number",
147
- description: options[:description],
148
- minimum: options[:minimum],
149
- maximum: options[:maximum],
150
- multipleOf: options[:multipleOf]
151
- }.compact
152
- when :integer
153
- {
154
- type: "integer",
155
- description: options[:description],
156
- minimum: options[:minimum],
157
- maximum: options[:maximum],
158
- multipleOf: options[:multipleOf]
159
- }.compact
160
- when :boolean
161
- {type: "boolean", description: options[:description]}.compact
162
- when :null
163
- {type: "null", description: options[:description]}.compact
164
- when :object
165
- sub_schema = Class.new(Schema)
166
- sub_schema.class_eval(&)
37
+ def description(description = nil)
38
+ @description = description if description
39
+ @description
40
+ end
41
+
42
+ def additional_properties(value = nil)
43
+ return @additional_properties ||= false if value.nil?
44
+ @additional_properties = value
45
+ end
167
46
 
168
- {
169
- type: "object",
170
- properties: sub_schema.properties,
171
- required: sub_schema.required_properties,
172
- additionalProperties: additional_properties,
173
- description: options[:description]
174
- }.compact
175
- else
176
- raise InvalidSchemaTypeError, type
47
+ def strict(value = nil)
48
+ if value.nil?
49
+ return @strict.nil? ? (@strict = true) : @strict
177
50
  end
51
+ @strict = value
178
52
  end
179
53
 
180
54
  def validate!
@@ -186,31 +60,6 @@ module RubyLLM
186
60
  validator = Validator.new(self)
187
61
  validator.valid?
188
62
  end
189
-
190
- private
191
-
192
- def add_property(name, definition, required:)
193
- properties[name.to_sym] = definition
194
- required_properties << name.to_sym if required
195
- end
196
-
197
- def determine_array_items(of, &)
198
- return collect_property_schemas_from_block(&).first if block_given?
199
- return build_property_schema(of) if primitive_type?(of)
200
- return reference(of) if of.is_a?(Symbol)
201
-
202
- raise InvalidArrayTypeError, of
203
- end
204
-
205
- def collect_property_schemas_from_block(&)
206
- collector = PropertySchemaCollector.new
207
- collector.collect(&)
208
- collector.schemas
209
- end
210
-
211
- def primitive_type?(type)
212
- type.is_a?(Symbol) && PRIMITIVE_TYPES.include?(type)
213
- end
214
63
  end
215
64
 
216
65
  def initialize(name = nil, description: nil)
@@ -218,28 +67,6 @@ module RubyLLM
218
67
  @description = description
219
68
  end
220
69
 
221
- def to_json_schema
222
- validate! # Validate schema before generating JSON
223
-
224
- {
225
- name: @name,
226
- description: @description,
227
- schema: {
228
- :type => "object",
229
- :properties => self.class.properties,
230
- :required => self.class.required_properties,
231
- :additionalProperties => self.class.additional_properties,
232
- :strict => self.class.strict,
233
- "$defs" => self.class.definitions
234
- }
235
- }
236
- end
237
-
238
- def to_json(*_args)
239
- validate! # Validate schema before generating JSON string
240
- JSON.pretty_generate(to_json_schema)
241
- end
242
-
243
70
  def validate!
244
71
  self.class.validate!
245
72
  end
@@ -250,7 +77,7 @@ module RubyLLM
250
77
 
251
78
  def method_missing(method_name, ...)
252
79
  if respond_to_missing?(method_name)
253
- send(method_name, ...)
80
+ self.class.send(method_name, ...)
254
81
  else
255
82
  super
256
83
  end
@@ -1,13 +1,22 @@
1
1
  namespace :release do
2
2
  desc "Release a new version of the gem"
3
- task :version do
3
+ task :version, [:message] do |t, args|
4
4
  # Load the current version from version.rb
5
- require_relative '../../lib/ruby_llm/schema/version'
5
+ require_relative "../../lib/ruby_llm/schema/version"
6
6
  version = RubyLlm::Schema::VERSION
7
-
7
+
8
8
  puts "Releasing version #{version}..."
9
-
10
- system "git tag v#{version}"
9
+
10
+ # Create git tag with optional message
11
+ # rake release:version["Fix critical bug in schema validation"]
12
+ if args[:message]
13
+ system "git tag -a v#{version} -m \"#{args[:message]}\""
14
+ puts "Created annotated tag v#{version} with message: #{args[:message]}"
15
+ else
16
+ system "git tag v#{version}"
17
+ puts "Created lightweight tag v#{version}"
18
+ end
19
+
11
20
  system "git push origin main"
12
21
  system "git push origin v#{version}"
13
22
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_llm-schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Friis
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-08-08 00:00:00.000000000 Z
10
+ date: 2025-08-22 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rspec
@@ -48,9 +48,10 @@ files:
48
48
  - README.md
49
49
  - Rakefile
50
50
  - lib/ruby_llm/schema.rb
51
+ - lib/ruby_llm/schema/dsl.rb
51
52
  - lib/ruby_llm/schema/errors.rb
52
53
  - lib/ruby_llm/schema/helpers.rb
53
- - lib/ruby_llm/schema/property_schema_collector.rb
54
+ - lib/ruby_llm/schema/json_output.rb
54
55
  - lib/ruby_llm/schema/validator.rb
55
56
  - lib/ruby_llm/schema/version.rb
56
57
  - lib/tasks/release.rake
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyLLM
4
- class Schema
5
- class PropertySchemaCollector
6
- attr_reader :schemas
7
-
8
- def initialize
9
- @schemas = []
10
- end
11
-
12
- def collect(&)
13
- instance_eval(&)
14
- end
15
-
16
- def string(**options)
17
- @schemas << Schema.build_property_schema(:string, **options)
18
- end
19
-
20
- def number(**options)
21
- @schemas << Schema.build_property_schema(:number, **options)
22
- end
23
-
24
- def integer(**options)
25
- @schemas << Schema.build_property_schema(:integer, **options)
26
- end
27
-
28
- def boolean(**options)
29
- @schemas << Schema.build_property_schema(:boolean, **options)
30
- end
31
-
32
- def null(**options)
33
- @schemas << Schema.build_property_schema(:null, **options)
34
- end
35
-
36
- def object(...)
37
- @schemas << Schema.build_property_schema(:object, ...)
38
- end
39
- end
40
- end
41
- end