easy_talk 0.1.7 → 0.1.9

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: f412e6a4ef70f8a8912def5e60e4f9a2fbb80a47c0f22e7f46af9caed9d153fa
4
- data.tar.gz: ee7bfc2e77fef086bff23db293eec6f6d7f47ed47488a803737e2831895feb88
3
+ metadata.gz: cac3597b203d800e1c15c79ea019a6d81080dd5c5ed669dc96500e262a32a505
4
+ data.tar.gz: 626bb67445db8ffa2d41df7a0b82ceba30db827ed0cb610f4d1b382d161a5191
5
5
  SHA512:
6
- metadata.gz: feb1884f28b4c0400ccbe3fb651f2d87e4650a25180ed804bab8c7b2493ebc7f0d7fb769271788a7dc0e0e6cdc6c2793fb1cbaa064df881aef2d797242b70860
7
- data.tar.gz: 1c2ac812a423169c0bc0d43afac4f86711acad7bbab28aeb40e249df65258be4cb845903edc585d43f835b2717b9fc4003817b0ae2c704d20a28ff583290f3c5
6
+ metadata.gz: e58629e7e0b4aff314f04d0a0d14f3129e0af8b54c23c1d061d57464648aa97caaf2db514353fcf34713d1d14113eb13c599ccc28b6106a3c5f06cd4197671af
7
+ data.tar.gz: f3ba1ec6c87ff2028a5bd26f22ebade4446717c8d9e27702c94f5e4080fd951885dd033a0d4f88078d44849cb7b251fc1dbb303f9da84b2a592bf85c1daaf9ef
data/.rubocop.yml CHANGED
@@ -1,5 +1,17 @@
1
+ require:
2
+ - rubocop-rake
3
+ - rubocop-rspec
4
+
1
5
  AllCops:
2
6
  TargetRubyVersion: 3.2
7
+
8
+ RSpec/FilePath:
9
+ SpecSuffixOnly: true
10
+
11
+ RSpec/ExampleLength:
12
+ Max: 10
13
+ Exclude:
14
+ - 'spec/easy_talk/examples/**/*'
3
15
 
4
16
  Metrics/BlockLength:
5
17
  Exclude:
@@ -11,4 +23,8 @@ Lint/ConstantDefinitionInBlock:
11
23
 
12
24
  Layout/LineLength:
13
25
  Exclude:
14
- - 'spec/**/*'
26
+ - 'spec/**/*'
27
+
28
+ RSpec/DescribeClass:
29
+ Exclude:
30
+ - 'spec/easy_talk/examples/**/*'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## [0.1.9] - 2024-04-29
2
+ - Added the ability to describe an object schema withing the define_schema block. Example:
3
+ ```ruby
4
+ ...
5
+ property :email, :object do
6
+ property :address, :string
7
+ property :verified, :boolean
8
+ end
9
+ ```
10
+
11
+ ## [0.1.8] - 2024-04-24
12
+ - mostly refactoring without changes to the public API.
13
+
1
14
  ## [0.1.7] - 2024-04-16
2
15
  - general cleanup and refactoring.
3
16
 
data/README.md CHANGED
@@ -12,7 +12,10 @@ class User
12
12
  title "User"
13
13
  description "A user of the system"
14
14
  property :name, String, description: "The user's name", title: "Full Name"
15
- property :email, String, description: "The user's email", format: "email", title: "Email Address"
15
+ property :email, :object do
16
+ property :address, String, format: "email", description: "The user's email", title: "Email Address"
17
+ property :verified, T::Boolean, description: "Whether the email is verified"
18
+ end
16
19
  property :group, String, enum: [1, 2, 3], default: 1, description: "The user's group"
17
20
  property :age, Integer, minimum: 18, maximum: 100, description: "The user's age"
18
21
  property :tags, T::Array[String], min_items: 1, unique_item: true, description: "The user's tags"
@@ -34,10 +37,23 @@ Calling `User.json_schema` will return the JSON Schema for the User class:
34
37
  "type": "string"
35
38
  },
36
39
  "email": {
37
- "title": "Email Address",
38
- "description": "The user's email",
39
- "type": "string",
40
- "format": "email"
40
+ "type": "object",
41
+ "properties": {
42
+ "address": {
43
+ "title": "Email Address",
44
+ "description": "The user's email",
45
+ "type": "string",
46
+ "format": "email"
47
+ },
48
+ "verified": {
49
+ "type": "boolean",
50
+ "description": "Whether the email is verified"
51
+ }
52
+ },
53
+ "required": [
54
+ "address",
55
+ "verified"
56
+ ]
41
57
  },
42
58
  "group": {
43
59
  "type": "number",
data/Rakefile CHANGED
@@ -2,11 +2,10 @@
2
2
 
3
3
  require 'bundler/gem_tasks'
4
4
  require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
5
6
 
6
7
  RSpec::Core::RakeTask.new(:spec)
7
8
 
8
- require 'rubocop/rake_task'
9
-
10
9
  RuboCop::RakeTask.new
11
10
 
12
11
  task default: %i[spec rubocop]
data/easy_talk.gemspec CHANGED
@@ -34,6 +34,12 @@ Gem::Specification.new do |spec|
34
34
  spec.add_dependency 'activesupport', '~> 7.0'
35
35
  spec.add_dependency 'json-schema', '~> 4'
36
36
  spec.add_dependency 'sorbet-runtime', '~> 0.5'
37
- spec.add_development_dependency 'pry-byebug', '>= 3.10.1'
37
+ spec.add_development_dependency 'pry-byebug', '>= 3.10'
38
38
  spec.add_development_dependency 'rake', '~> 13.1'
39
+ spec.add_development_dependency 'rspec', '~> 3.0'
40
+ spec.add_development_dependency 'rspec-json_expectations', '~> 2.0'
41
+ spec.add_development_dependency 'rspec-mocks', '~> 3.13'
42
+ spec.add_development_dependency 'rubocop', '~> 1.21'
43
+ spec.add_development_dependency 'rubocop-rake', '~> 0.6'
44
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.29'
39
45
  end
@@ -8,10 +8,10 @@ module EasyTalk
8
8
  class ObjectBuilder < BaseBuilder
9
9
  extend T::Sig
10
10
 
11
- attr_reader :klass, :schema
11
+ attr_reader :schema
12
12
 
13
13
  VALID_OPTIONS = {
14
- properties: { type: T::Hash[Symbol, T.untyped], key: :properties },
14
+ properties: { type: T::Hash[T.any(Symbol, String), T.untyped], key: :properties },
15
15
  additional_properties: { type: T::Boolean, key: :additionalProperties },
16
16
  subschemas: { type: T::Array[T.untyped], key: :subschemas },
17
17
  required: { type: T::Array[Symbol], key: :required },
@@ -33,42 +33,58 @@ module EasyTalk
33
33
 
34
34
  private
35
35
 
36
- def properties_from_schema_definition(properties)
36
+ def properties_from_schema_definition
37
+ properties = schema.delete(:properties) || {}
37
38
  properties.each_with_object({}) do |(property_name, options), context|
38
- @required_properties << property_name unless options[:type].respond_to?(:nilable?) && options[:type].nilable?
39
- context[property_name] = Property.new(property_name, options[:type], options[:constraints])
39
+ add_required_property(property_name, options)
40
+ context[property_name] = build_property(property_name, options)
40
41
  end
41
42
  end
42
43
 
43
- def subschemas_from_schema_definition(subschemas)
44
+ def add_required_property(property_name, options)
45
+ return unless options.is_a?(Hash) && !(options[:type].respond_to?(:nilable?) && options[:type].nilable?)
46
+
47
+ @required_properties << property_name
48
+ end
49
+
50
+ def build_property(property_name, options)
51
+ if options.is_a?(EasyTalk::SchemaDefinition)
52
+ ObjectBuilder.new(options).build
53
+ else
54
+ Property.new(property_name, options[:type], options[:constraints])
55
+ end
56
+ end
57
+
58
+ def subschemas_from_schema_definition
59
+ subschemas = schema.delete(:subschemas) || []
44
60
  subschemas.each do |subschema|
45
- definitions = subschema.items.each_with_object({}) do |item, hash|
46
- hash[item.name] = item.schema
47
- end
48
- schema[:defs] = definitions
49
- references = subschema.items.map do |item|
50
- { '$ref': item.ref_template }
51
- end
52
- schema[subschema.name] = references
61
+ add_definitions(subschema)
62
+ add_references(subschema)
63
+ end
64
+ end
65
+
66
+ def add_definitions(subschema)
67
+ definitions = subschema.items.each_with_object({}) do |item, hash|
68
+ hash[item.name] = item.schema
69
+ end
70
+ schema[:defs] = definitions
71
+ end
72
+
73
+ def add_references(subschema)
74
+ references = subschema.items.map do |item|
75
+ { '$ref': item.ref_template }
53
76
  end
77
+ schema[subschema.name] = references
54
78
  end
55
79
 
56
80
  def options
57
- subschemas_from_schema_definition(subschemas)
58
81
  @options = schema
59
- @options[:properties] = properties_from_schema_definition(properties)
82
+ subschemas_from_schema_definition
83
+ @options[:properties] = properties_from_schema_definition
60
84
  @options[:required] = @required_properties
61
85
  @options.reject! { |_key, value| [nil, [], {}].include?(value) }
62
86
  @options
63
87
  end
64
-
65
- def properties
66
- schema.delete(:properties) || {}
67
- end
68
-
69
- def subschemas
70
- schema.delete(:subschemas) || []
71
- end
72
88
  end
73
89
  end
74
90
  end
@@ -17,6 +17,16 @@ require_relative 'builders/union_builder'
17
17
 
18
18
  # frozen_string_literal: true
19
19
 
20
+ # EasyTalk module provides classes for building JSON schema properties.
21
+ #
22
+ # This module contains the `Property` class, which is used to build a JSON schema property.
23
+ # It also defines a constant `TYPE_TO_BUILDER` which maps property types to their respective builders.
24
+ #
25
+ # Example usage:
26
+ # property = EasyTalk::Property.new(:name, 'String', minLength: 3, maxLength: 50)
27
+ # property.build
28
+ #
29
+ # @see EasyTalk::Property
20
30
  module EasyTalk
21
31
  # Property class for building a JSON schema property.
22
32
  class Property
@@ -56,22 +66,36 @@ module EasyTalk
56
66
  raise ArgumentError, 'property type is missing' if type.blank?
57
67
  end
58
68
 
69
+ # Builds the property based on the specified type, constraints, and builder.
70
+ #
71
+ # If the type responds to the `schema` method, it returns the schema of the type.
72
+ # Otherwise, it returns 'object'.
73
+ #
74
+ # If a builder is specified, it uses the builder to build the property.
75
+ # The arguments passed to the builder depend on whether the builder is a collection type or not.
76
+ #
77
+ # @return [Object] The built property.
59
78
  def build
60
- if builder
61
- if builder.collection_type?
62
- builder.new(name, type, constraints).build
63
- else
64
- builder.new(name, constraints).build
65
- end
66
- else
67
- type.respond_to?(:schema) ? type.schema : 'object'
68
- end
79
+ return type.respond_to?(:schema) ? type.schema : 'object' unless builder
80
+
81
+ args = builder.collection_type? ? [name, type, constraints] : [name, constraints]
82
+ builder.new(*args).build
69
83
  end
70
84
 
85
+ # Converts the object to a JSON representation.
86
+ #
87
+ # @param _args [Array] Optional arguments
88
+ # @return [Hash] The JSON representation of the object
71
89
  def as_json(*_args)
72
90
  build.as_json
73
91
  end
74
92
 
93
+ # Returns the builder associated with the property type.
94
+ #
95
+ # The builder is responsible for constructing the property based on its type.
96
+ # It looks up the builder based on the type's class name or name.
97
+ #
98
+ # @return [Builder] The builder associated with the property type.
75
99
  def builder
76
100
  TYPE_TO_BUILDER[type.class.name.to_s] || TYPE_TO_BUILDER[type.name.to_s]
77
101
  end
@@ -32,10 +32,19 @@ module EasyTalk
32
32
  @schema[:subschemas] += subschemas
33
33
  end
34
34
 
35
- sig { params(name: Symbol, type: T.untyped, constraints: T.untyped).void }
36
- def property(name, type, **constraints)
35
+ sig do
36
+ params(name: T.any(Symbol, String), type: T.untyped, constraints: T.untyped, blk: T.nilable(T.proc.void)).void
37
+ end
38
+ def property(name, type, **constraints, &blk)
37
39
  @schema[:properties] ||= {}
38
- @schema[:properties][name] = { type:, constraints: }
40
+
41
+ if block_given?
42
+ property_schema = SchemaDefinition.new(name)
43
+ property_schema.instance_eval(&blk)
44
+ @schema[:properties][name] = property_schema
45
+ else
46
+ @schema[:properties][name] = { type:, constraints: }
47
+ end
39
48
  end
40
49
  end
41
50
  end
@@ -2,7 +2,13 @@
2
2
 
3
3
  module EasyTalk
4
4
  module Tools
5
+ # FunctionBuilder is a module that builds a hash with the function type and function details.
6
+ # The return value is typically passed as argument to LLM function calling APIs.
5
7
  module FunctionBuilder
8
+ # Creates a new function object based on the given model.
9
+ #
10
+ # @param [Model] model The EasyTalk model containing the function details.
11
+ # @return [Hash] The function object.
6
12
  def self.new(model)
7
13
  {
8
14
  type: 'function',
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EasyTalk
4
- VERSION = '0.1.7'
4
+ VERSION = '0.1.9'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_talk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergio Bayona
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-16 00:00:00.000000000 Z
11
+ date: 2024-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 3.10.1
61
+ version: '3.10'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 3.10.1
68
+ version: '3.10'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,90 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '13.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-json_expectations
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec-mocks
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.13'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.13'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.21'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1.21'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop-rake
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.6'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.6'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-rspec
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '2.29'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '2.29'
83
167
  description: Generate json-schema from plain Ruby classes.
84
168
  email:
85
169
  - bayona.sergio@gmail.com
@@ -146,7 +230,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
230
  - !ruby/object:Gem::Version
147
231
  version: '0'
148
232
  requirements: []
149
- rubygems_version: 3.5.3
233
+ rubygems_version: 3.5.9
150
234
  signing_key:
151
235
  specification_version: 4
152
236
  summary: Generate json-schema from Ruby classes.