easy_talk 0.1.7 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
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.