composio 0.1.15 → 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +4 -4
  3. data/README.md +250 -202
  4. data/lib/composio/api/actions_api.rb +201 -6
  5. data/lib/composio/api/admin_api.rb +78 -0
  6. data/lib/composio/api/auth_api.rb +77 -0
  7. data/lib/composio/api/cli_api.rb +266 -0
  8. data/lib/composio/api/connections_api.rb +124 -6
  9. data/lib/composio/api/event_logs_api.rb +0 -318
  10. data/lib/composio/api/integrations_api.rb +8 -4
  11. data/lib/composio/api/logs_api.rb +19 -4
  12. data/lib/composio/api/triggers_api.rb +9 -2
  13. data/lib/composio/models/action_execution_req_dto.rb +31 -4
  14. data/lib/composio/models/action_get_nla_inputs_req_dto.rb +22 -4
  15. data/lib/composio/models/actions_query_dto.rb +22 -4
  16. data/lib/composio/models/app_query_dto.rb +1 -1
  17. data/lib/composio/models/client_dto.rb +374 -0
  18. data/lib/composio/models/client_dto_created_at.rb +102 -0
  19. data/lib/composio/models/client_dto_last_subscribed_at.rb +102 -0
  20. data/lib/composio/models/client_dto_updated_at.rb +102 -0
  21. data/lib/composio/models/client_info_res_dto.rb +235 -0
  22. data/lib/composio/models/connection_params.rb +15 -4
  23. data/lib/composio/models/connection_with_app_data.rb +15 -4
  24. data/lib/composio/models/create_connector_payload_dto.rb +12 -7
  25. data/lib/composio/models/expected_input_fields_dto.rb +346 -0
  26. data/lib/composio/models/get_connections_query_dto.rb +15 -4
  27. data/lib/composio/models/get_connector_info_res_dto.rb +1 -1
  28. data/lib/composio/models/get_logs_dto.rb +14 -4
  29. data/lib/composio/models/ingest_data_dto.rb +21 -1
  30. data/lib/composio/models/initiate_connection_payload_dto.rb +19 -18
  31. data/lib/composio/models/list_triggers_query_dto.rb +11 -1
  32. data/lib/composio/models/sdk_error_res_dto.rb +221 -0
  33. data/lib/composio/models/session_info_dto.rb +224 -0
  34. data/lib/composio/models/tools_execute_req_dto.rb +22 -4
  35. data/lib/composio/models/trigger_response_dto.rb +14 -4
  36. data/lib/composio/models/update_connection_labels_payload_dto.rb +222 -0
  37. data/lib/composio/version.rb +1 -1
  38. data/lib/composio.rb +12 -3
  39. data/spec/api/actions_api_spec.rb +25 -0
  40. data/spec/api/admin_api_spec.rb +11 -0
  41. data/spec/api/auth_api_spec.rb +11 -0
  42. data/spec/api/cli_api_spec.rb +63 -0
  43. data/spec/api/connections_api_spec.rb +14 -0
  44. data/spec/api/event_logs_api_spec.rb +0 -43
  45. data/spec/api/logs_api_spec.rb +1 -0
  46. data/spec/api/triggers_api_spec.rb +1 -0
  47. data/spec/models/action_execution_req_dto_spec.rb +18 -0
  48. data/spec/models/action_get_nla_inputs_req_dto_spec.rb +12 -0
  49. data/spec/models/actions_query_dto_spec.rb +12 -0
  50. data/spec/models/client_dto_created_at_spec.rb +25 -0
  51. data/spec/models/client_dto_last_subscribed_at_spec.rb +25 -0
  52. data/spec/models/client_dto_spec.rb +100 -0
  53. data/spec/models/client_dto_updated_at_spec.rb +25 -0
  54. data/spec/models/client_info_res_dto_spec.rb +34 -0
  55. data/spec/models/connection_params_spec.rb +6 -0
  56. data/spec/models/connection_with_app_data_spec.rb +6 -0
  57. data/spec/models/create_connector_payload_dto_spec.rb +6 -0
  58. data/spec/models/expected_input_fields_dto_spec.rb +82 -0
  59. data/spec/models/get_connections_query_dto_spec.rb +6 -0
  60. data/spec/models/get_logs_dto_spec.rb +6 -0
  61. data/spec/models/ingest_data_dto_spec.rb +12 -0
  62. data/spec/models/initiate_connection_payload_dto_spec.rb +6 -0
  63. data/spec/models/list_triggers_query_dto_spec.rb +6 -0
  64. data/spec/models/sdk_error_res_dto_spec.rb +28 -0
  65. data/spec/models/session_info_dto_spec.rb +34 -0
  66. data/spec/models/tools_execute_req_dto_spec.rb +12 -0
  67. data/spec/models/trigger_response_dto_spec.rb +6 -0
  68. data/spec/models/update_connection_labels_payload_dto_spec.rb +28 -0
  69. metadata +32 -4
  70. data/spec/api/payment_api_spec.rb +0 -83
@@ -35,6 +35,10 @@ module Composio
35
35
 
36
36
  attr_accessor :show_all
37
37
 
38
+ attr_accessor :page
39
+
40
+ attr_accessor :offset
41
+
38
42
  # Attribute mapping from ruby-style variable name to JSON key.
39
43
  def self.attribute_map
40
44
  {
@@ -47,7 +51,9 @@ module Composio
47
51
  :'actions' => :'actions',
48
52
  :'usecase_limit' => :'usecaseLimit',
49
53
  :'filter_important_actions' => :'filterImportantActions',
50
- :'show_all' => :'showAll'
54
+ :'show_all' => :'showAll',
55
+ :'page' => :'page',
56
+ :'offset' => :'offset'
51
57
  }
52
58
  end
53
59
 
@@ -68,7 +74,9 @@ module Composio
68
74
  :'actions' => :'String',
69
75
  :'usecase_limit' => :'Float',
70
76
  :'filter_important_actions' => :'Boolean',
71
- :'show_all' => :'Boolean'
77
+ :'show_all' => :'Boolean',
78
+ :'page' => :'Float',
79
+ :'offset' => :'Float'
72
80
  }
73
81
  end
74
82
 
@@ -132,6 +140,14 @@ module Composio
132
140
  if attributes.key?(:'show_all')
133
141
  self.show_all = attributes[:'show_all']
134
142
  end
143
+
144
+ if attributes.key?(:'page')
145
+ self.page = attributes[:'page']
146
+ end
147
+
148
+ if attributes.key?(:'offset')
149
+ self.offset = attributes[:'offset']
150
+ end
135
151
  end
136
152
 
137
153
  # Show invalid properties with the reasons. Usually used together with valid?
@@ -161,7 +177,9 @@ module Composio
161
177
  actions == o.actions &&
162
178
  usecase_limit == o.usecase_limit &&
163
179
  filter_important_actions == o.filter_important_actions &&
164
- show_all == o.show_all
180
+ show_all == o.show_all &&
181
+ page == o.page &&
182
+ offset == o.offset
165
183
  end
166
184
 
167
185
  # @see the `==` method
@@ -173,7 +191,7 @@ module Composio
173
191
  # Calculates hash code according to all attributes.
174
192
  # @return [Integer] Hash code
175
193
  def hash
176
- [tags, app_names, use_case, show_enabled_only, limit, apps, actions, usecase_limit, filter_important_actions, show_all].hash
194
+ [tags, app_names, use_case, show_enabled_only, limit, apps, actions, usecase_limit, filter_important_actions, show_all, page, offset].hash
177
195
  end
178
196
 
179
197
  # Builds the object from hash
@@ -17,7 +17,7 @@ module Composio
17
17
  # Additional fields to include in the response
18
18
  attr_accessor :additional_fields
19
19
 
20
- # Whether to include local tools or not
20
+ # Enter 'true' or 'false'
21
21
  attr_accessor :include_local
22
22
 
23
23
  # Attribute mapping from ruby-style variable name to JSON key.
@@ -0,0 +1,374 @@
1
+ =begin
2
+ #Composio OpenAPI
3
+
4
+ #Composio SDK: Equip your agent with high-quality tools and build your real-world usecase
5
+
6
+ The version of the OpenAPI document: 1.0.0
7
+ =end
8
+
9
+ require 'date'
10
+ require 'time'
11
+
12
+ module Composio
13
+ # Client information
14
+ class ClientDTO
15
+ # Auto-generated ID of the client
16
+ attr_accessor :auto_id
17
+
18
+ # Unique ID of the client
19
+ attr_accessor :id
20
+
21
+ # Name of the client
22
+ attr_accessor :name
23
+
24
+ # Email of the client
25
+ attr_accessor :email
26
+
27
+ attr_accessor :created_at
28
+
29
+ attr_accessor :updated_at
30
+
31
+ # API key for the client
32
+ attr_accessor :api_key
33
+
34
+ # Webhook URL for the client
35
+ attr_accessor :webhook_url
36
+
37
+ # Event webhook URL for the client
38
+ attr_accessor :event_webhook_url
39
+
40
+ # Secret for webhook authentication
41
+ attr_accessor :webhook_secret
42
+
43
+ # Whether triggers are enabled for the client
44
+ attr_accessor :triggers_enabled
45
+
46
+ attr_accessor :last_subscribed_at
47
+
48
+ # Client's subscription plan
49
+ attr_accessor :plan
50
+
51
+ # Attribute mapping from ruby-style variable name to JSON key.
52
+ def self.attribute_map
53
+ {
54
+ :'auto_id' => :'autoId',
55
+ :'id' => :'id',
56
+ :'name' => :'name',
57
+ :'email' => :'email',
58
+ :'created_at' => :'createdAt',
59
+ :'updated_at' => :'updatedAt',
60
+ :'api_key' => :'apiKey',
61
+ :'webhook_url' => :'webhookURL',
62
+ :'event_webhook_url' => :'eventWebhookURL',
63
+ :'webhook_secret' => :'webhookSecret',
64
+ :'triggers_enabled' => :'triggersEnabled',
65
+ :'last_subscribed_at' => :'lastSubscribedAt',
66
+ :'plan' => :'plan'
67
+ }
68
+ end
69
+
70
+ # Returns all the JSON keys this model knows about
71
+ def self.acceptable_attributes
72
+ attribute_map.values
73
+ end
74
+
75
+ # Attribute type mapping.
76
+ def self.openapi_types
77
+ {
78
+ :'auto_id' => :'Float',
79
+ :'id' => :'String',
80
+ :'name' => :'String',
81
+ :'email' => :'String',
82
+ :'created_at' => :'ClientDTOCreatedAt',
83
+ :'updated_at' => :'ClientDTOUpdatedAt',
84
+ :'api_key' => :'String',
85
+ :'webhook_url' => :'String',
86
+ :'event_webhook_url' => :'String',
87
+ :'webhook_secret' => :'String',
88
+ :'triggers_enabled' => :'Boolean',
89
+ :'last_subscribed_at' => :'ClientDTOLastSubscribedAt',
90
+ :'plan' => :'String'
91
+ }
92
+ end
93
+
94
+ # List of attributes with nullable: true
95
+ def self.openapi_nullable
96
+ Set.new([
97
+ ])
98
+ end
99
+
100
+ # Initializes the object
101
+ # @param [Hash] attributes Model attributes in the form of hash
102
+ def initialize(attributes = {})
103
+ if (!attributes.is_a?(Hash))
104
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Composio::ClientDTO` initialize method"
105
+ end
106
+
107
+ # check to see if the attribute exists and convert string to symbol for hash key
108
+ attributes = attributes.each_with_object({}) { |(k, v), h|
109
+ if (!self.class.attribute_map.key?(k.to_sym))
110
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Composio::ClientDTO`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
111
+ end
112
+ h[k.to_sym] = v
113
+ }
114
+
115
+ if attributes.key?(:'auto_id')
116
+ self.auto_id = attributes[:'auto_id']
117
+ end
118
+
119
+ if attributes.key?(:'id')
120
+ self.id = attributes[:'id']
121
+ end
122
+
123
+ if attributes.key?(:'name')
124
+ self.name = attributes[:'name']
125
+ end
126
+
127
+ if attributes.key?(:'email')
128
+ self.email = attributes[:'email']
129
+ end
130
+
131
+ if attributes.key?(:'created_at')
132
+ self.created_at = attributes[:'created_at']
133
+ end
134
+
135
+ if attributes.key?(:'updated_at')
136
+ self.updated_at = attributes[:'updated_at']
137
+ end
138
+
139
+ if attributes.key?(:'api_key')
140
+ self.api_key = attributes[:'api_key']
141
+ end
142
+
143
+ if attributes.key?(:'webhook_url')
144
+ self.webhook_url = attributes[:'webhook_url']
145
+ end
146
+
147
+ if attributes.key?(:'event_webhook_url')
148
+ self.event_webhook_url = attributes[:'event_webhook_url']
149
+ end
150
+
151
+ if attributes.key?(:'webhook_secret')
152
+ self.webhook_secret = attributes[:'webhook_secret']
153
+ end
154
+
155
+ if attributes.key?(:'triggers_enabled')
156
+ self.triggers_enabled = attributes[:'triggers_enabled']
157
+ end
158
+
159
+ if attributes.key?(:'last_subscribed_at')
160
+ self.last_subscribed_at = attributes[:'last_subscribed_at']
161
+ end
162
+
163
+ if attributes.key?(:'plan')
164
+ self.plan = attributes[:'plan']
165
+ end
166
+ end
167
+
168
+ # Show invalid properties with the reasons. Usually used together with valid?
169
+ # @return Array for valid properties with the reasons
170
+ def list_invalid_properties
171
+ invalid_properties = Array.new
172
+ if @auto_id.nil?
173
+ invalid_properties.push('invalid value for "auto_id", auto_id cannot be nil.')
174
+ end
175
+
176
+ if @id.nil?
177
+ invalid_properties.push('invalid value for "id", id cannot be nil.')
178
+ end
179
+
180
+ if @name.nil?
181
+ invalid_properties.push('invalid value for "name", name cannot be nil.')
182
+ end
183
+
184
+ if @email.nil?
185
+ invalid_properties.push('invalid value for "email", email cannot be nil.')
186
+ end
187
+
188
+ if @created_at.nil?
189
+ invalid_properties.push('invalid value for "created_at", created_at cannot be nil.')
190
+ end
191
+
192
+ if @updated_at.nil?
193
+ invalid_properties.push('invalid value for "updated_at", updated_at cannot be nil.')
194
+ end
195
+
196
+ if @triggers_enabled.nil?
197
+ invalid_properties.push('invalid value for "triggers_enabled", triggers_enabled cannot be nil.')
198
+ end
199
+
200
+ if @plan.nil?
201
+ invalid_properties.push('invalid value for "plan", plan cannot be nil.')
202
+ end
203
+
204
+ invalid_properties
205
+ end
206
+
207
+ # Check to see if the all the properties in the model are valid
208
+ # @return true if the model is valid
209
+ def valid?
210
+ return false if @auto_id.nil?
211
+ return false if @id.nil?
212
+ return false if @name.nil?
213
+ return false if @email.nil?
214
+ return false if @created_at.nil?
215
+ return false if @updated_at.nil?
216
+ return false if @triggers_enabled.nil?
217
+ return false if @plan.nil?
218
+ true
219
+ end
220
+
221
+ # Checks equality by comparing each attribute.
222
+ # @param [Object] Object to be compared
223
+ def ==(o)
224
+ return true if self.equal?(o)
225
+ self.class == o.class &&
226
+ auto_id == o.auto_id &&
227
+ id == o.id &&
228
+ name == o.name &&
229
+ email == o.email &&
230
+ created_at == o.created_at &&
231
+ updated_at == o.updated_at &&
232
+ api_key == o.api_key &&
233
+ webhook_url == o.webhook_url &&
234
+ event_webhook_url == o.event_webhook_url &&
235
+ webhook_secret == o.webhook_secret &&
236
+ triggers_enabled == o.triggers_enabled &&
237
+ last_subscribed_at == o.last_subscribed_at &&
238
+ plan == o.plan
239
+ end
240
+
241
+ # @see the `==` method
242
+ # @param [Object] Object to be compared
243
+ def eql?(o)
244
+ self == o
245
+ end
246
+
247
+ # Calculates hash code according to all attributes.
248
+ # @return [Integer] Hash code
249
+ def hash
250
+ [auto_id, id, name, email, created_at, updated_at, api_key, webhook_url, event_webhook_url, webhook_secret, triggers_enabled, last_subscribed_at, plan].hash
251
+ end
252
+
253
+ # Builds the object from hash
254
+ # @param [Hash] attributes Model attributes in the form of hash
255
+ # @return [Object] Returns the model itself
256
+ def self.build_from_hash(attributes)
257
+ new.build_from_hash(attributes)
258
+ end
259
+
260
+ # Builds the object from hash
261
+ # @param [Hash] attributes Model attributes in the form of hash
262
+ # @return [Object] Returns the model itself
263
+ def build_from_hash(attributes)
264
+ return nil unless attributes.is_a?(Hash)
265
+ attributes = attributes.transform_keys(&:to_sym)
266
+ self.class.openapi_types.each_pair do |key, type|
267
+ if attributes[self.class.attribute_map[key]].nil? && self.class.openapi_nullable.include?(key)
268
+ self.send("#{key}=", nil)
269
+ elsif type =~ /\AArray<(.*)>/i
270
+ # check to ensure the input is an array given that the attribute
271
+ # is documented as an array but the input is not
272
+ if attributes[self.class.attribute_map[key]].is_a?(Array)
273
+ self.send("#{key}=", attributes[self.class.attribute_map[key]].map { |v| _deserialize($1, v) })
274
+ end
275
+ elsif !attributes[self.class.attribute_map[key]].nil?
276
+ self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
277
+ end
278
+ end
279
+
280
+ self
281
+ end
282
+
283
+ # Deserializes the data based on type
284
+ # @param string type Data type
285
+ # @param string value Value to be deserialized
286
+ # @return [Object] Deserialized data
287
+ def _deserialize(type, value)
288
+ case type.to_sym
289
+ when :Time
290
+ Time.parse(value)
291
+ when :Date
292
+ Date.parse(value)
293
+ when :String
294
+ value.to_s
295
+ when :Integer
296
+ value.to_i
297
+ when :Float
298
+ value.to_f
299
+ when :Boolean
300
+ if value.to_s =~ /\A(true|t|yes|y|1)\z/i
301
+ true
302
+ else
303
+ false
304
+ end
305
+ when :Object
306
+ # generic object (usually a Hash), return directly
307
+ value
308
+ when /\AArray<(?<inner_type>.+)>\z/
309
+ inner_type = Regexp.last_match[:inner_type]
310
+ value.map { |v| _deserialize(inner_type, v) }
311
+ when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
312
+ k_type = Regexp.last_match[:k_type]
313
+ v_type = Regexp.last_match[:v_type]
314
+ {}.tap do |hash|
315
+ value.each do |k, v|
316
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
317
+ end
318
+ end
319
+ else # model
320
+ # models (e.g. Pet) or oneOf
321
+ klass = Composio.const_get(type)
322
+ klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
323
+ end
324
+ end
325
+
326
+ # Returns the string representation of the object
327
+ # @return [String] String presentation of the object
328
+ def to_s
329
+ to_hash.to_s
330
+ end
331
+
332
+ # to_body is an alias to to_hash (backward compatibility)
333
+ # @return [Hash] Returns the object in the form of hash
334
+ def to_body
335
+ to_hash
336
+ end
337
+
338
+ # Returns the object in the form of hash
339
+ # @return [Hash] Returns the object in the form of hash
340
+ def to_hash
341
+ hash = {}
342
+ self.class.attribute_map.each_pair do |attr, param|
343
+ value = self.send(attr)
344
+ if value.nil?
345
+ is_nullable = self.class.openapi_nullable.include?(attr)
346
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
347
+ end
348
+
349
+ hash[param] = _to_hash(value)
350
+ end
351
+ hash
352
+ end
353
+
354
+ # Outputs non-array value in the form of hash
355
+ # For object, use to_hash. Otherwise, just return the value
356
+ # @param [Object] value Any valid value
357
+ # @return [Hash] Returns the value in the form of hash
358
+ def _to_hash(value)
359
+ if value.is_a?(Array)
360
+ value.compact.map { |v| _to_hash(v) }
361
+ elsif value.is_a?(Hash)
362
+ {}.tap do |hash|
363
+ value.each { |k, v| hash[k] = _to_hash(v) }
364
+ end
365
+ elsif value.respond_to? :to_hash
366
+ value.to_hash
367
+ else
368
+ value
369
+ end
370
+ end
371
+
372
+ end
373
+
374
+ end
@@ -0,0 +1,102 @@
1
+ =begin
2
+ #Composio OpenAPI
3
+
4
+ #Composio SDK: Equip your agent with high-quality tools and build your real-world usecase
5
+
6
+ The version of the OpenAPI document: 1.0.0
7
+ =end
8
+
9
+ require 'date'
10
+ require 'time'
11
+
12
+ module Composio
13
+ # Creation timestamp
14
+ module ClientDTOCreatedAt
15
+ class << self
16
+ # List of class defined in oneOf (OpenAPI v3)
17
+ def openapi_one_of
18
+ [
19
+ :'Date',
20
+ :'Time'
21
+ ]
22
+ end
23
+
24
+ # Builds the object
25
+ # @param [Mixed] Data to be matched against the list of oneOf items
26
+ # @return [Object] Returns the model or the data itself
27
+ def build(data)
28
+ # Go through the list of oneOf items and attempt to identify the appropriate one.
29
+ # Note:
30
+ # - We do not attempt to check whether exactly one item matches.
31
+ # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 })
32
+ # due to the way the deserialization is made in the base_object template (it just casts without verifying).
33
+ # - TODO: scalar values are de facto behaving as if they were nullable.
34
+ # - TODO: logging when debugging is set.
35
+ openapi_one_of.each do |klass|
36
+ begin
37
+ next if klass == :AnyType # "nullable: true"
38
+ typed_data = find_and_cast_into_type(klass, data)
39
+ return typed_data if typed_data
40
+ rescue # rescue all errors so we keep iterating even if the current item lookup raises
41
+ end
42
+ end
43
+
44
+ openapi_one_of.include?(:AnyType) ? data : nil
45
+ end
46
+
47
+ private
48
+
49
+ SchemaMismatchError = Class.new(StandardError)
50
+
51
+ # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse.
52
+ def find_and_cast_into_type(klass, data)
53
+ return if data.nil?
54
+
55
+ case klass.to_s
56
+ when 'Boolean'
57
+ return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass)
58
+ when 'Float'
59
+ return data if data.instance_of?(Float)
60
+ when 'Integer'
61
+ return data if data.instance_of?(Integer)
62
+ when 'Time'
63
+ return Time.parse(data)
64
+ when 'Date'
65
+ return Date.parse(data)
66
+ when 'String'
67
+ return data if data.instance_of?(String)
68
+ when 'Object' # "type: object"
69
+ return data if data.instance_of?(Hash)
70
+ when /\AArray<(?<sub_type>.+)>\z/ # "type: array"
71
+ if data.instance_of?(Array)
72
+ sub_type = Regexp.last_match[:sub_type]
73
+ return data.map { |item| find_and_cast_into_type(sub_type, item) }
74
+ end
75
+ when /\AHash<String, (?<sub_type>.+)>\z/ # "type: object" with "additionalProperties: { ... }"
76
+ if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) }
77
+ sub_type = Regexp.last_match[:sub_type]
78
+ return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) }
79
+ end
80
+ else # model
81
+ const = Composio.const_get(klass)
82
+ if const
83
+ if const.respond_to?(:openapi_one_of) # nested oneOf model
84
+ model = const.build(data)
85
+ return model if model
86
+ else
87
+ # raise if data contains keys that are not known to the model
88
+ raise unless (data.keys - const.acceptable_attributes).empty?
89
+ model = const.build_from_hash(data)
90
+ return model if model && model.valid?
91
+ end
92
+ end
93
+ end
94
+
95
+ raise # if no match by now, raise
96
+ rescue
97
+ raise SchemaMismatchError, "#{data} doesn't match the #{klass} type"
98
+ end
99
+ end
100
+ end
101
+
102
+ end
@@ -0,0 +1,102 @@
1
+ =begin
2
+ #Composio OpenAPI
3
+
4
+ #Composio SDK: Equip your agent with high-quality tools and build your real-world usecase
5
+
6
+ The version of the OpenAPI document: 1.0.0
7
+ =end
8
+
9
+ require 'date'
10
+ require 'time'
11
+
12
+ module Composio
13
+ # Last subscription timestamp
14
+ module ClientDTOLastSubscribedAt
15
+ class << self
16
+ # List of class defined in oneOf (OpenAPI v3)
17
+ def openapi_one_of
18
+ [
19
+ :'Date',
20
+ :'Time'
21
+ ]
22
+ end
23
+
24
+ # Builds the object
25
+ # @param [Mixed] Data to be matched against the list of oneOf items
26
+ # @return [Object] Returns the model or the data itself
27
+ def build(data)
28
+ # Go through the list of oneOf items and attempt to identify the appropriate one.
29
+ # Note:
30
+ # - We do not attempt to check whether exactly one item matches.
31
+ # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 })
32
+ # due to the way the deserialization is made in the base_object template (it just casts without verifying).
33
+ # - TODO: scalar values are de facto behaving as if they were nullable.
34
+ # - TODO: logging when debugging is set.
35
+ openapi_one_of.each do |klass|
36
+ begin
37
+ next if klass == :AnyType # "nullable: true"
38
+ typed_data = find_and_cast_into_type(klass, data)
39
+ return typed_data if typed_data
40
+ rescue # rescue all errors so we keep iterating even if the current item lookup raises
41
+ end
42
+ end
43
+
44
+ openapi_one_of.include?(:AnyType) ? data : nil
45
+ end
46
+
47
+ private
48
+
49
+ SchemaMismatchError = Class.new(StandardError)
50
+
51
+ # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse.
52
+ def find_and_cast_into_type(klass, data)
53
+ return if data.nil?
54
+
55
+ case klass.to_s
56
+ when 'Boolean'
57
+ return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass)
58
+ when 'Float'
59
+ return data if data.instance_of?(Float)
60
+ when 'Integer'
61
+ return data if data.instance_of?(Integer)
62
+ when 'Time'
63
+ return Time.parse(data)
64
+ when 'Date'
65
+ return Date.parse(data)
66
+ when 'String'
67
+ return data if data.instance_of?(String)
68
+ when 'Object' # "type: object"
69
+ return data if data.instance_of?(Hash)
70
+ when /\AArray<(?<sub_type>.+)>\z/ # "type: array"
71
+ if data.instance_of?(Array)
72
+ sub_type = Regexp.last_match[:sub_type]
73
+ return data.map { |item| find_and_cast_into_type(sub_type, item) }
74
+ end
75
+ when /\AHash<String, (?<sub_type>.+)>\z/ # "type: object" with "additionalProperties: { ... }"
76
+ if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) }
77
+ sub_type = Regexp.last_match[:sub_type]
78
+ return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) }
79
+ end
80
+ else # model
81
+ const = Composio.const_get(klass)
82
+ if const
83
+ if const.respond_to?(:openapi_one_of) # nested oneOf model
84
+ model = const.build(data)
85
+ return model if model
86
+ else
87
+ # raise if data contains keys that are not known to the model
88
+ raise unless (data.keys - const.acceptable_attributes).empty?
89
+ model = const.build_from_hash(data)
90
+ return model if model && model.valid?
91
+ end
92
+ end
93
+ end
94
+
95
+ raise # if no match by now, raise
96
+ rescue
97
+ raise SchemaMismatchError, "#{data} doesn't match the #{klass} type"
98
+ end
99
+ end
100
+ end
101
+
102
+ end