retell-sdk-unofficial 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5280bd7a0c19d1b1c38c2ae5e92cebc8879e33a4e1353d7f1e3710f6058df34d
4
+ data.tar.gz: 9d883ffb78ba89504d1b86a42b2dd736b7c2acb4ed5d08d74fe96f16aa6e9f6c
5
+ SHA512:
6
+ metadata.gz: 86ac04d901a367116597afe11c969c22b4213032fc7fc7d7120047920fe0546be3af937a21705a8a9d8e98eb6a8de898cadb9b645997487e9e1b8169070886c7
7
+ data.tar.gz: 66da02d303ad6122dc3b6cccd0f2ff5bbf12e12c2ff961e77ab0ff4c5d12289cc328ba73824ca5073cfb28cd4fe357c60fcc76b73c2aa36572d40f2d2a586321
@@ -0,0 +1,73 @@
1
+ module Retell
2
+ module SDK
3
+ module Unofficial
4
+ class Agent < Base
5
+ @attributes = [
6
+ :agent_id, :llm_websocket_url, :voice_id, :agent_name, :ambient_sound, :ambient_sound_volume, :backchannel_frequency, :backchannel_words, :boosted_keywords, :enable_backchannel,:enable_voicemail_detection, :end_call_after_silence_ms, :fallback_voice_ids, :interruption_sensitivity, :language, :last_modification_timestamp, :max_call_duration_ms, :normalize_for_speech, :opt_out_sensitive_data_storage, :post_call_analysis_data, :pronunciation_dictionary, :reminder_max_count, :reminder_trigger_ms, :responsiveness, :voice_model, :voice_speed, :voice_temperature, :voicemail_detection_timeout_ms, :voicemail_message, :volume, :webhook_url
7
+ ]
8
+
9
+ @writeable_attributes = [
10
+ :llm_websocket_url, :voice_id, :agent_name, :ambient_sound, :ambient_sound_volume, :backchannel_frequency, :backchannel_words, :boosted_keywords, :enable_backchannel, :enable_voicemail_detection, :end_call_after_silence_ms, :fallback_voice_ids, :interruption_sensitivity, :language, :max_call_duration_ms, :normalize_for_speech, :opt_out_sensitive_data_storage, :post_call_analysis_data, :pronounciation_dictionary, :reminder_max_count, :reminder_trigger_ms, :responsiveness, :voice_model, :voice_speed, :voice_temperature, :voicemail_detection_timeout_ms, :voicemail_message, :volume, :webhook_url
11
+ ]
12
+
13
+ attr_reader *@attributes
14
+
15
+ @writeable_attributes.each do |attr|
16
+ define_method("#{attr}=") do |value|
17
+ self[attr] = value
18
+ end
19
+ end
20
+
21
+ def id
22
+ agent_id
23
+ end
24
+
25
+ def name
26
+ agent_name
27
+ end
28
+
29
+ def name=(value)
30
+ self[:agent_name] = value
31
+ end
32
+
33
+ def voice
34
+ voice_id
35
+ end
36
+
37
+ def voice=(value)
38
+ self[:voice_id] = value
39
+ end
40
+
41
+ def fallback_voices
42
+ fallback_voice_ids
43
+ end
44
+
45
+ def fallback_voices=(value)
46
+ self[:fallback_voice_ids] = value
47
+ end
48
+
49
+ def retrieve
50
+ @client.agent.retrieve(self)
51
+ end
52
+
53
+ def update(**params)
54
+ update_params = @changed_attributes.merge(params)
55
+
56
+ if update_params.any?
57
+ updated_agent = @client.agent.update(self, **update_params)
58
+ self.class.attributes.each do |attr|
59
+ instance_variable_set("@#{attr}", updated_agent.send(attr))
60
+ end
61
+ @changed_attributes.clear
62
+ end
63
+
64
+ self
65
+ end
66
+
67
+ def delete
68
+ @client.agent.delete(self)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,11 @@
1
+ module Retell
2
+ module SDK
3
+ module Unofficial
4
+ class AgentList < BaseList
5
+ def initialize(raw_response)
6
+ super(:agents, raw_response)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,348 @@
1
+ module Retell
2
+ module SDK
3
+ module Unofficial
4
+ module API
5
+ class Agent
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def create(
11
+ llm_websocket_url:,
12
+ voice_id:,
13
+ agent_name: nil,
14
+ ambient_sound: nil,
15
+ ambient_sound_volume: nil,
16
+ backchannel_frequency: nil,
17
+ backchannel_words: nil,
18
+ boosted_keywords: nil,
19
+ enable_backchannel: nil,
20
+ enable_voicemail_detection: nil,
21
+ end_call_after_silence_ms: nil,
22
+ fallback_voice_ids: nil,
23
+ fallback_voices: nil,
24
+ interruption_sensitivity: nil,
25
+ language: nil,
26
+ max_call_duration_ms: nil,
27
+ name: nil,
28
+ normalize_for_speech: nil,
29
+ opt_out_sensitive_data_storage: nil,
30
+ post_call_analysis_data: nil,
31
+ pronunciation_dictionary: nil,
32
+ reminder_max_count: nil,
33
+ reminder_trigger_ms: nil,
34
+ responsiveness: nil,
35
+ voice: nil,
36
+ voice_model: nil,
37
+ voice_speed: nil,
38
+ voice_temperature: nil,
39
+ voicemail_detection_timeout_ms: nil,
40
+ voicemail_message: nil,
41
+ volume: nil,
42
+ webhook_url: nil,
43
+ extra_headers: nil,
44
+ extra_query: nil,
45
+ extra_body: nil,
46
+ timeout: nil
47
+ )
48
+ agent_name = agent_name || name
49
+ voice_id = voice_id || voice
50
+ fallback_voice_ids = fallback_voice_ids || fallback_voices
51
+
52
+ voice_id = voice_id.is_a?(Retell::SDK::Unofficial::Voice) ? voice_id.voice_id : voice_id
53
+ fallback_voice_ids = fallback_voice_ids.is_a?(Array) ? verify_fallback_voice_ids(fallback_voice_ids) : fallback_voice_ids
54
+
55
+ validate_voice_model(voice_model)
56
+ validate_ambient_sound(ambient_sound)
57
+ validate_language(language)
58
+ validate_numeric_range(ambient_sound_volume, 'ambient_sound_volume', 0, 1)
59
+ validate_numeric_range(backchannel_frequency, 'backchannel_frequency', 0, 1)
60
+ validate_numeric_range(interruption_sensitivity, 'interruption_sensitivity', 0, 1)
61
+ validate_numeric_range(responsiveness, 'responsiveness', 0, 1)
62
+ validate_numeric_range(voice_speed, 'voice_speed', 0.5, 2)
63
+ validate_numeric_range(voice_temperature, 'voice_temperature', 0, 2)
64
+ validate_numeric_range(volume, 'volume', 0, 2)
65
+
66
+ payload = {
67
+ llm_websocket_url: llm_websocket_url,
68
+ voice_id: voice_id,
69
+ agent_name: agent_name,
70
+ ambient_sound: ambient_sound,
71
+ ambient_sound_volume: ambient_sound_volume&.to_f,
72
+ backchannel_frequency: backchannel_frequency&.to_f,
73
+ backchannel_words: backchannel_words,
74
+ boosted_keywords: boosted_keywords,
75
+ enable_backchannel: enable_backchannel,
76
+ enable_voicemail_detection: enable_voicemail_detection,
77
+ end_call_after_silence_ms: end_call_after_silence_ms,
78
+ fallback_voice_ids: fallback_voice_ids,
79
+ interruption_sensitivity: interruption_sensitivity&.to_f,
80
+ language: language,
81
+ max_call_duration_ms: max_call_duration_ms,
82
+ normalize_for_speech: normalize_for_speech,
83
+ opt_out_sensitive_data_storage: opt_out_sensitive_data_storage,
84
+ post_call_analysis_data: post_call_analysis_data,
85
+ pronunciation_dictionary: pronunciation_dictionary,
86
+ reminder_max_count: reminder_max_count,
87
+ reminder_trigger_ms: reminder_trigger_ms,
88
+ responsiveness: responsiveness&.to_f,
89
+ voice_model: voice_model,
90
+ voice_speed: voice_speed&.to_f,
91
+ voice_temperature: voice_temperature&.to_f,
92
+ voicemail_detection_timeout_ms: voicemail_detection_timeout_ms,
93
+ voicemail_message: voicemail_message,
94
+ volume: volume&.to_f,
95
+ webhook_url: webhook_url
96
+ }.compact
97
+
98
+ options = @client.make_request_options(
99
+ extra_headers: extra_headers,
100
+ extra_query: extra_query,
101
+ extra_body: extra_body,
102
+ timeout: timeout
103
+ )
104
+
105
+ @client.post('/create-agent', payload, **options)
106
+ end
107
+
108
+ def retrieve(
109
+ agent_or_id,
110
+ extra_headers: nil,
111
+ extra_query: nil,
112
+ extra_body: nil,
113
+ timeout: nil
114
+ )
115
+ agent_id = agent_or_id.is_a?(Retell::SDK::Unofficial::Agent) ? agent_or_id.agent_id : agent_or_id
116
+
117
+ options = @client.make_request_options(
118
+ extra_headers: extra_headers,
119
+ extra_query: extra_query,
120
+ extra_body: extra_body,
121
+ timeout: timeout
122
+ )
123
+
124
+ @client.get("/get-agent/#{agent_id}", **options)
125
+ end
126
+
127
+ def update(
128
+ agent_or_id,
129
+ llm_websocket_url: nil,
130
+ voice_id: nil,
131
+ agent_name: nil,
132
+ ambient_sound: nil,
133
+ ambient_sound_volume: nil,
134
+ backchannel_frequency: nil,
135
+ backchannel_words: nil,
136
+ boosted_keywords: nil,
137
+ enable_backchannel: nil,
138
+ enable_voicemail_detection: nil,
139
+ end_call_after_silence_ms: nil,
140
+ fallback_voices: nil,
141
+ fallback_voice_ids: nil,
142
+ interruption_sensitivity: nil,
143
+ language: nil,
144
+ max_call_duration_ms: nil,
145
+ name: nil,
146
+ normalize_for_speech: nil,
147
+ opt_out_sensitive_data_storage: nil,
148
+ post_call_analysis_data: nil,
149
+ pronunciation_dictionary: nil,
150
+ reminder_max_count: nil,
151
+ reminder_trigger_ms: nil,
152
+ responsiveness: nil,
153
+ voice: nil,
154
+ voice_model: nil,
155
+ voice_speed: nil,
156
+ voice_temperature: nil,
157
+ voicemail_detection_timeout_ms: nil,
158
+ voicemail_message: nil,
159
+ volume: nil,
160
+ webhook_url: nil,
161
+ extra_headers: nil,
162
+ extra_query: nil,
163
+ extra_body: nil,
164
+ timeout: nil
165
+ )
166
+ agent_name = agent_name || name
167
+ voice_id = voice_id || voice
168
+ fallback_voice_ids = fallback_voice_ids || fallback_voices
169
+
170
+ agent_id = agent_or_id.is_a?(Retell::SDK::Unofficial::Agent) ? agent_or_id.agent_id : agent_or_id
171
+ voice_id = voice_id.is_a?(Retell::SDK::Unofficial::Voice) ? voice_id.voice_id : voice_id
172
+ fallback_voice_ids = fallback_voice_ids.is_a?(Array) ? verify_fallback_voice_ids(fallback_voice_ids) : fallback_voice_ids
173
+
174
+ validate_voice_model(voice_model) if voice_model
175
+ validate_ambient_sound(ambient_sound) if ambient_sound
176
+ validate_language(language) if language
177
+ validate_numeric_range(ambient_sound_volume, 'ambient_sound_volume', 0, 1) if ambient_sound_volume
178
+ validate_numeric_range(backchannel_frequency, 'backchannel_frequency', 0, 1) if backchannel_frequency
179
+ validate_numeric_range(interruption_sensitivity, 'interruption_sensitivity', 0, 1) if interruption_sensitivity
180
+ validate_numeric_range(responsiveness, 'responsiveness', 0, 1) if responsiveness
181
+ validate_numeric_range(voice_speed, 'voice_speed', 0.5, 2) if voice_speed
182
+ validate_numeric_range(voice_temperature, 'voice_temperature', 0, 2) if voice_temperature
183
+ validate_numeric_range(volume, 'volume', 0, 2) if volume
184
+ validate_pronunciation_dictionary(pronunciation_dictionary) if pronunciation_dictionary
185
+ validate_post_call_analysis_data(post_call_analysis_data) if post_call_analysis_data
186
+
187
+ payload = {
188
+ llm_websocket_url: llm_websocket_url,
189
+ voice_id: voice_id,
190
+ agent_name: agent_name,
191
+ ambient_sound: ambient_sound,
192
+ ambient_sound_volume: ambient_sound_volume&.to_f,
193
+ backchannel_frequency: backchannel_frequency&.to_f,
194
+ backchannel_words: backchannel_words,
195
+ boosted_keywords: boosted_keywords,
196
+ enable_backchannel: enable_backchannel,
197
+ enable_voicemail_detection: enable_voicemail_detection,
198
+ end_call_after_silence_ms: end_call_after_silence_ms,
199
+ fallback_voice_ids: fallback_voice_ids,
200
+ interruption_sensitivity: interruption_sensitivity&.to_f,
201
+ language: language,
202
+ max_call_duration_ms: max_call_duration_ms,
203
+ normalize_for_speech: normalize_for_speech,
204
+ opt_out_sensitive_data_storage: opt_out_sensitive_data_storage,
205
+ post_call_analysis_data: post_call_analysis_data,
206
+ pronunciation_dictionary: pronunciation_dictionary,
207
+ reminder_max_count: reminder_max_count,
208
+ reminder_trigger_ms: reminder_trigger_ms,
209
+ responsiveness: responsiveness&.to_f,
210
+ voice_model: voice_model,
211
+ voice_speed: voice_speed&.to_f,
212
+ voice_temperature: voice_temperature&.to_f,
213
+ voicemail_detection_timeout_ms: voicemail_detection_timeout_ms,
214
+ voicemail_message: voicemail_message,
215
+ webhook_url: webhook_url
216
+ }.compact
217
+
218
+ options = @client.make_request_options(
219
+ extra_headers: extra_headers,
220
+ extra_query: extra_query,
221
+ extra_body: extra_body,
222
+ timeout: timeout
223
+ )
224
+
225
+ @client.patch("/update-agent/#{agent_id}", payload, **options)
226
+ end
227
+
228
+ def list(
229
+ extra_headers: nil,
230
+ extra_query: nil,
231
+ extra_body: nil,
232
+ timeout: nil
233
+ )
234
+ options = @client.make_request_options(
235
+ extra_headers: extra_headers,
236
+ extra_query: extra_query,
237
+ extra_body: extra_body,
238
+ timeout: timeout
239
+ )
240
+ @client.get('/list-agents', **options)
241
+ end
242
+
243
+ def delete(
244
+ agent_or_id,
245
+ extra_headers: nil,
246
+ extra_query: nil,
247
+ extra_body: nil,
248
+ timeout: nil
249
+ )
250
+ agent_id = agent_or_id.is_a?(Retell::SDK::Unofficial::Agent) ? agent_or_id.agent_id : agent_or_id
251
+
252
+ options = @client.make_request_options(
253
+ extra_headers: extra_headers,
254
+ extra_query: extra_query,
255
+ extra_body: extra_body,
256
+ timeout: timeout
257
+ )
258
+ @client.delete("/delete-agent/#{agent_id}", **options)
259
+ nil
260
+ end
261
+
262
+ private
263
+
264
+ def verify_fallback_voice_ids(fallback_voice_ids)
265
+ fallback_voice_ids.map do |voice_or_id|
266
+ voice_or_id.is_a?(Retell::SDK::Unofficial::Voice) ? voice_or_id.voice_id : voice_or_id
267
+ end
268
+ end
269
+
270
+ def validate_voice_model(voice_model)
271
+ return if voice_model.nil?
272
+ valid_models = ["eleven_turbo_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2"]
273
+ unless valid_models.include?(voice_model)
274
+ raise ArgumentError, "Invalid voice_model. Must be one of: #{valid_models.join(', ')}"
275
+ end
276
+ end
277
+
278
+ def validate_ambient_sound(ambient_sound)
279
+ return if ambient_sound.nil?
280
+ valid_sounds = ["coffee-shop", "convention-hall", "summer-outdoor", "mountain-outdoor", "static-noise", "call-center"]
281
+ unless valid_sounds.include?(ambient_sound)
282
+ raise ArgumentError, "Invalid ambient_sound. Must be one of: #{valid_sounds.join(', ')}"
283
+ end
284
+ end
285
+
286
+ def validate_language(language)
287
+ return if language.nil?
288
+ valid_languages = ["en-US", "en-IN", "en-GB", "de-DE", "es-ES", "es-419", "hi-IN", "ja-JP", "pt-PT", "pt-BR", "fr-FR", "multi"]
289
+ unless valid_languages.include?(language)
290
+ raise ArgumentError, "Invalid language. Must be one of: #{valid_languages.join(', ')}"
291
+ end
292
+ end
293
+
294
+ def validate_numeric_range(value, param_name, min, max)
295
+ return if value.nil?
296
+ value = value.to_f
297
+ unless value >= min && value <= max
298
+ raise ArgumentError, "#{param_name} must be between #{min} and #{max}"
299
+ end
300
+ end
301
+
302
+ def validate_pronunciation_dictionary(pronunciation_dictionary)
303
+ pronunciation_dictionary.each do |entry|
304
+ unless entry.is_a?(Hash) && entry[:word].is_a?(String) && entry[:alphabet].is_a?(String) && entry[:phoneme].is_a?(String)
305
+ raise ArgumentError, "Invalid pronunciation_dictionary entry: #{entry}"
306
+ end
307
+ unless ['ipa', 'cmu'].include?(entry[:alphabet])
308
+ raise ArgumentError, "Invalid alphabet in pronunciation_dictionary: #{entry[:alphabet]}. Must be 'ipa' or 'cmu'."
309
+ end
310
+ end
311
+ end
312
+
313
+ def validate_post_call_analysis_data(post_call_analysis_data)
314
+ post_call_analysis_data.each do |data|
315
+ unless data.is_a?(Hash) && data[:type].is_a?(String) && data[:name].is_a?(String) && data[:description].is_a?(String)
316
+ raise ArgumentError, "Invalid post_call_analysis_data entry: #{data}"
317
+ end
318
+ case data[:type]
319
+ when 'string'
320
+ validate_string_analysis_data(data)
321
+ when 'enum'
322
+ validate_enum_analysis_data(data)
323
+ when 'boolean'
324
+ # No additional validation needed for boolean type
325
+ when 'number'
326
+ # No additional validation needed for number type
327
+ else
328
+ raise ArgumentError, "Invalid type in post_call_analysis_data: #{data[:type]}"
329
+ end
330
+ end
331
+ end
332
+
333
+ def validate_string_analysis_data(data)
334
+ if data[:examples] && !data[:examples].is_a?(Array)
335
+ raise ArgumentError, "Examples for string type must be an array"
336
+ end
337
+ end
338
+
339
+ def validate_enum_analysis_data(data)
340
+ unless data[:choices].is_a?(Array) && !data[:choices].empty?
341
+ raise ArgumentError, "Choices for enum type must be a non-empty array"
342
+ end
343
+ end
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
@@ -0,0 +1,212 @@
1
+ module Retell
2
+ module SDK
3
+ module Unofficial
4
+ module API
5
+ class Call
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def create_web_call(
11
+ agent_id:,
12
+ metadata: nil,
13
+ retell_llm_dynamic_variables: nil,
14
+ extra_headers: nil,
15
+ extra_query: nil,
16
+ extra_body: nil,
17
+ timeout: nil
18
+ )
19
+ agent_id = agent_id.is_a?(Retell::SDK::Unofficial::Agent) ? agent_id.agent_id : agent_id
20
+
21
+ validate_non_empty_string(agent_id, 'agent_id')
22
+
23
+ payload = {
24
+ agent_id: agent_id,
25
+ metadata: metadata,
26
+ retell_llm_dynamic_variables: retell_llm_dynamic_variables
27
+ }.compact
28
+
29
+ options = @client.make_request_options(
30
+ extra_headers: extra_headers,
31
+ extra_query: extra_query,
32
+ extra_body: extra_body,
33
+ timeout: timeout
34
+ )
35
+
36
+ @client.post('/v2/create-web-call', payload, **options)
37
+ end
38
+
39
+ def create_phone_call(
40
+ from_number:,
41
+ to_number:,
42
+ override_agent_id: nil,
43
+ metadata: nil,
44
+ retell_llm_dynamic_variables: nil,
45
+ extra_headers: nil,
46
+ extra_query: nil,
47
+ extra_body: nil,
48
+ timeout: nil
49
+ )
50
+ override_agent_id = override_agent_id.is_a?(Retell::SDK::Unofficial::Agent) ? override_agent_id.agent_id : override_agent_id
51
+
52
+ validate_phone_number(from_number, 'from_number')
53
+ validate_phone_number(to_number, 'to_number')
54
+ validate_non_empty_string(override_agent_id, 'override_agent_id') if override_agent_id
55
+
56
+ payload = {
57
+ from_number: from_number,
58
+ to_number: to_number,
59
+ override_agent_id: override_agent_id,
60
+ metadata: metadata,
61
+ retell_llm_dynamic_variables: retell_llm_dynamic_variables
62
+ }.compact
63
+
64
+ options = @client.make_request_options(
65
+ extra_headers: extra_headers,
66
+ extra_query: extra_query,
67
+ extra_body: extra_body,
68
+ timeout: timeout
69
+ )
70
+
71
+ @client.post('/v2/create-phone-call', payload, **options)
72
+ end
73
+
74
+ def register(
75
+ agent_id:,
76
+ direction: nil,
77
+ from_number: nil,
78
+ to_number: nil,
79
+ metadata: nil,
80
+ retell_llm_dynamic_variables: nil,
81
+ extra_headers: nil,
82
+ extra_query: nil,
83
+ extra_body: nil,
84
+ timeout: nil
85
+ )
86
+ agent_id = agent_id.is_a?(Retell::SDK::Unofficial::Agent) ? agent_id.agent_id : agent_id
87
+
88
+ validate_non_empty_string(agent_id, 'agent_id')
89
+ validate_direction(direction) if direction
90
+ validate_phone_number(from_number, 'from_number') if from_number
91
+ validate_phone_number(to_number, 'to_number') if to_number
92
+
93
+
94
+ payload = {
95
+ agent_id: agent_id,
96
+ direction: direction,
97
+ from_number: from_number,
98
+ to_number: to_number,
99
+ metadata: metadata,
100
+ retell_llm_dynamic_variables: retell_llm_dynamic_variables
101
+ }.compact
102
+
103
+ options = @client.make_request_options(
104
+ extra_headers: extra_headers,
105
+ extra_query: extra_query,
106
+ extra_body: extra_body,
107
+ timeout: timeout
108
+ )
109
+
110
+ @client.post('/v2/register-phone-call', payload, **options)
111
+ end
112
+
113
+ def retrieve(
114
+ call_or_id,
115
+ extra_headers: nil,
116
+ extra_query: nil,
117
+ extra_body: nil,
118
+ timeout: nil
119
+ )
120
+ call_id = (call_or_id.is_a?(Retell::SDK::Unofficial::PhoneCall) || call_or_id.is_a?(Retell::SDK::Unofficial::WebCall)) ? call_or_id.call_id : call_or_id
121
+
122
+ validate_non_empty_string(call_id, 'call_id')
123
+
124
+ options = @client.make_request_options(
125
+ extra_headers: extra_headers,
126
+ extra_query: extra_query,
127
+ extra_body: extra_body,
128
+ timeout: timeout
129
+ )
130
+
131
+ @client.get("/v2/get-call/#{call_id}", **options)
132
+ end
133
+
134
+ def list(
135
+ filter_criteria: nil,
136
+ limit: nil,
137
+ pagination_key: nil,
138
+ sort_order: nil,
139
+ extra_headers: nil,
140
+ extra_query: nil,
141
+ extra_body: nil,
142
+ timeout: nil
143
+ )
144
+ validate_positive_integer(limit, 'limit') if limit
145
+ validate_sort_order(sort_order) if sort_order
146
+ validate_filter_criteria(filter_criteria) if filter_criteria
147
+
148
+ payload = {
149
+ filter_criteria: filter_criteria,
150
+ limit: limit,
151
+ pagination_key: pagination_key,
152
+ sort_order: sort_order
153
+ }.compact
154
+
155
+ options = @client.make_request_options(
156
+ extra_headers: extra_headers,
157
+ extra_query: extra_query,
158
+ extra_body: extra_body,
159
+ timeout: timeout
160
+ )
161
+
162
+ @client.post('/v2/list-calls', payload, **options)
163
+ end
164
+
165
+ private
166
+
167
+ def validate_non_empty_string(value, param_name)
168
+ raise ArgumentError, "#{param_name} must be a non-empty string" if value.to_s.empty?
169
+ end
170
+
171
+ def validate_phone_number(value, param_name)
172
+ raise ArgumentError, "#{param_name} must be a valid phone number in E.164 format" unless value.match?(/^\+[1-9]\d{1,14}$/)
173
+ end
174
+
175
+ def validate_direction(value)
176
+ raise ArgumentError, "direction must be either 'inbound' or 'outbound'" unless ['inbound', 'outbound'].include?(value)
177
+ end
178
+
179
+ def validate_positive_integer(value, param_name)
180
+ raise ArgumentError, "#{param_name} must be a positive integer" unless value.is_a?(Integer) && value > 0
181
+ end
182
+
183
+ def validate_sort_order(value)
184
+ raise ArgumentError, "sort_order must be either 'ascending' or 'descending'" unless ['ascending', 'descending'].include?(value)
185
+ end
186
+
187
+ def validate_filter_criteria(criteria)
188
+ criteria.each do |key, value|
189
+ case key
190
+ when :after_end_timestamp, :after_start_timestamp, :before_end_timestamp, :before_start_timestamp
191
+ validate_timestamp(value, key.to_s)
192
+ when :agent_id
193
+ if value.is_a?(Array)
194
+ raise ArgumentError, "agent_id array cannot be empty" if value.empty?
195
+ value.each { |id| validate_non_empty_string(id, 'agent_id') }
196
+ else
197
+ validate_non_empty_string(value, 'agent_id')
198
+ end
199
+ else
200
+ raise ArgumentError, "Invalid filter criteria key: #{key}"
201
+ end
202
+ end
203
+ end
204
+
205
+ def validate_timestamp(value, param_name)
206
+ raise ArgumentError, "#{param_name} must be a valid timestamp" unless value.is_a?(Integer) || value.is_a?(Time)
207
+ end
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,28 @@
1
+ module Retell
2
+ module SDK
3
+ module Unofficial
4
+ module API
5
+ class Concurrency
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def retrieve(
11
+ extra_headers: nil,
12
+ extra_query: nil,
13
+ extra_body: nil,
14
+ timeout: nil
15
+ )
16
+ options = @client.make_request_options(
17
+ extra_headers: extra_headers,
18
+ extra_query: extra_query,
19
+ extra_body: extra_body,
20
+ timeout: timeout
21
+ )
22
+ @client.request(:get, '/get-concurrency', {}, **options)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end