voiceml 0.9.2 → 0.9.3
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 +4 -4
- data/README.md +17 -13
- data/lib/voiceml/client.rb +53 -13
- data/lib/voiceml/errors.rb +15 -2
- data/lib/voiceml/models/accounts.rb +47 -3
- data/lib/voiceml/models/applications.rb +6 -0
- data/lib/voiceml/models/assistants_v1.rb +40 -0
- data/lib/voiceml/models/calls.rb +4 -0
- data/lib/voiceml/models/common.rb +35 -4
- data/lib/voiceml/models/conferences.rb +8 -0
- data/lib/voiceml/models/conversations_v1.rb +131 -29
- data/lib/voiceml/models/diagnostics.rb +33 -12
- data/lib/voiceml/models/exports.rb +58 -0
- data/lib/voiceml/models/incoming_phone_numbers.rb +4 -0
- data/lib/voiceml/models/media.rb +4 -0
- data/lib/voiceml/models/messages.rb +29 -0
- data/lib/voiceml/models/messaging_v1.rb +35 -2
- data/lib/voiceml/models/monitor_v1.rb +54 -0
- data/lib/voiceml/models/notifications.rb +2 -0
- data/lib/voiceml/models/outgoing_caller_ids.rb +6 -0
- data/lib/voiceml/models/payments.rb +2 -0
- data/lib/voiceml/models/pricing.rb +38 -4
- data/lib/voiceml/models/queues.rb +8 -0
- data/lib/voiceml/models/recordings.rb +5 -1
- data/lib/voiceml/models/routes_v2.rb +6 -2
- data/lib/voiceml/models/sip.rb +34 -6
- data/lib/voiceml/models/sip_registrations.rb +49 -0
- data/lib/voiceml/models/siprec.rb +5 -17
- data/lib/voiceml/models/streams.rb +4 -16
- data/lib/voiceml/models/transcriptions.rb +35 -4
- data/lib/voiceml/models/usage_records.rb +48 -0
- data/lib/voiceml/models/user_defined_messages.rb +2 -0
- data/lib/voiceml/models/voice_v1.rb +29 -19
- data/lib/voiceml/request_validator.rb +125 -0
- data/lib/voiceml/resources/accounts.rb +75 -0
- data/lib/voiceml/resources/applications.rb +3 -1
- data/lib/voiceml/resources/assistants_v1.rb +53 -77
- data/lib/voiceml/resources/base.rb +138 -16
- data/lib/voiceml/resources/calls.rb +34 -49
- data/lib/voiceml/resources/conferences.rb +26 -5
- data/lib/voiceml/resources/conversations_v1.rb +147 -172
- data/lib/voiceml/resources/diagnostics.rb +20 -35
- data/lib/voiceml/resources/exports.rb +36 -0
- data/lib/voiceml/resources/incoming_phone_numbers.rb +53 -32
- data/lib/voiceml/resources/messages.rb +79 -15
- data/lib/voiceml/resources/messaging_v1.rb +47 -13
- data/lib/voiceml/resources/monitor_v1.rb +68 -0
- data/lib/voiceml/resources/notifications.rb +1 -1
- data/lib/voiceml/resources/outgoing_caller_ids.rb +77 -0
- data/lib/voiceml/resources/pricing.rb +13 -5
- data/lib/voiceml/resources/queues.rb +6 -5
- data/lib/voiceml/resources/recordings.rb +39 -5
- data/lib/voiceml/resources/routes_v2.rb +10 -4
- data/lib/voiceml/resources/sip.rb +30 -11
- data/lib/voiceml/resources/transcriptions.rb +40 -0
- data/lib/voiceml/resources/usage_records.rb +51 -0
- data/lib/voiceml/resources/voice_v1.rb +31 -38
- data/lib/voiceml/transport.rb +277 -230
- data/lib/voiceml/version.rb +1 -1
- data/lib/voiceml.rb +14 -15
- metadata +18 -6
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'base'
|
|
4
|
+
|
|
3
5
|
require_relative '../models/assistants_v1'
|
|
4
6
|
|
|
5
7
|
module VoiceML
|
|
@@ -63,6 +65,8 @@ module VoiceML
|
|
|
63
65
|
# Fetch returns the AssistantWithToolsAndKnowledge shape (tools + knowledge inline).
|
|
64
66
|
# ============================================================================
|
|
65
67
|
class AssistantsV1AssistantsResource
|
|
68
|
+
include V1Pages
|
|
69
|
+
include FieldMapping
|
|
66
70
|
CREATE_FIELDS = %i[name owner personality_prompt model customer_ai segment_credential].freeze
|
|
67
71
|
UPDATE_FIELDS = %i[name owner personality_prompt model customer_ai segment_credential].freeze
|
|
68
72
|
|
|
@@ -81,39 +85,29 @@ module VoiceML
|
|
|
81
85
|
def create(name:, **kwargs)
|
|
82
86
|
kwargs[:name] = name
|
|
83
87
|
AssistantsV1Assistant.from_hash(
|
|
84
|
-
@transport.request(:post, '/v1/Assistants', json:
|
|
88
|
+
@transport.request(:post, '/v1/Assistants', json: json_params(CREATE_FIELDS, kwargs))
|
|
85
89
|
)
|
|
86
90
|
end
|
|
87
91
|
|
|
88
92
|
def fetch(id)
|
|
89
93
|
AssistantsV1AssistantWithToolsAndKnowledge.from_hash(
|
|
90
|
-
@transport.request(:get, "/v1/Assistants/#{id}")
|
|
94
|
+
@transport.request(:get, "/v1/Assistants/#{encode_path_segment(id)}")
|
|
91
95
|
)
|
|
92
96
|
end
|
|
93
97
|
|
|
94
98
|
def update(id, **kwargs)
|
|
95
99
|
AssistantsV1Assistant.from_hash(
|
|
96
|
-
@transport.request(:put, "/v1/Assistants/#{id}", json:
|
|
100
|
+
@transport.request(:put, "/v1/Assistants/#{encode_path_segment(id)}", json: json_params(UPDATE_FIELDS, kwargs))
|
|
97
101
|
)
|
|
98
102
|
end
|
|
99
103
|
|
|
100
104
|
def delete(id)
|
|
101
|
-
@transport.request(:delete, "/v1/Assistants/#{id}")
|
|
105
|
+
@transport.request(:delete, "/v1/Assistants/#{encode_path_segment(id)}")
|
|
102
106
|
nil
|
|
103
107
|
end
|
|
104
108
|
|
|
105
109
|
private
|
|
106
110
|
|
|
107
|
-
def build_json(keys, kwargs)
|
|
108
|
-
out = {}
|
|
109
|
-
keys.each do |k|
|
|
110
|
-
v = kwargs[k]
|
|
111
|
-
next if v.nil?
|
|
112
|
-
|
|
113
|
-
out[k.to_s] = v
|
|
114
|
-
end
|
|
115
|
-
out
|
|
116
|
-
end
|
|
117
111
|
end
|
|
118
112
|
|
|
119
113
|
# ============================================================================
|
|
@@ -150,6 +144,8 @@ module VoiceML
|
|
|
150
144
|
|
|
151
145
|
# /v1/Assistants/{id}/Tools — list attached + attach/detach single Tool.
|
|
152
146
|
class AssistantsV1AssistantToolsScope
|
|
147
|
+
include V1Pages
|
|
148
|
+
include FieldMapping
|
|
153
149
|
def initialize(transport, assistant_id)
|
|
154
150
|
@transport = transport
|
|
155
151
|
@assistant_id = assistant_id
|
|
@@ -159,25 +155,27 @@ module VoiceML
|
|
|
159
155
|
params = {}
|
|
160
156
|
params['PageSize'] = page_size unless page_size.nil?
|
|
161
157
|
AssistantsV1ToolList.new(
|
|
162
|
-
@transport.request(:get, "/v1/Assistants/#{@assistant_id}/Tools", params: params)
|
|
158
|
+
@transport.request(:get, "/v1/Assistants/#{encode_path_segment(@assistant_id)}/Tools", params: params)
|
|
163
159
|
)
|
|
164
160
|
end
|
|
165
161
|
|
|
166
162
|
# POST /v1/Assistants/{id}/Tools/{toolId} — 204 No Content on success.
|
|
167
163
|
def attach(tool_id)
|
|
168
|
-
@transport.request(:post, "/v1/Assistants/#{@assistant_id}/Tools/#{tool_id}")
|
|
164
|
+
@transport.request(:post, "/v1/Assistants/#{encode_path_segment(@assistant_id)}/Tools/#{encode_path_segment(tool_id)}")
|
|
169
165
|
nil
|
|
170
166
|
end
|
|
171
167
|
|
|
172
168
|
# DELETE /v1/Assistants/{id}/Tools/{toolId} — 204 No Content on success.
|
|
173
169
|
def detach(tool_id)
|
|
174
|
-
@transport.request(:delete, "/v1/Assistants/#{@assistant_id}/Tools/#{tool_id}")
|
|
170
|
+
@transport.request(:delete, "/v1/Assistants/#{encode_path_segment(@assistant_id)}/Tools/#{encode_path_segment(tool_id)}")
|
|
175
171
|
nil
|
|
176
172
|
end
|
|
177
173
|
end
|
|
178
174
|
|
|
179
175
|
# /v1/Assistants/{id}/Knowledge — list attached + attach/detach single Knowledge.
|
|
180
176
|
class AssistantsV1AssistantKnowledgeScope
|
|
177
|
+
include V1Pages
|
|
178
|
+
include FieldMapping
|
|
181
179
|
def initialize(transport, assistant_id)
|
|
182
180
|
@transport = transport
|
|
183
181
|
@assistant_id = assistant_id
|
|
@@ -187,25 +185,27 @@ module VoiceML
|
|
|
187
185
|
params = {}
|
|
188
186
|
params['PageSize'] = page_size unless page_size.nil?
|
|
189
187
|
AssistantsV1KnowledgeList.new(
|
|
190
|
-
@transport.request(:get, "/v1/Assistants/#{@assistant_id}/Knowledge", params: params)
|
|
188
|
+
@transport.request(:get, "/v1/Assistants/#{encode_path_segment(@assistant_id)}/Knowledge", params: params)
|
|
191
189
|
)
|
|
192
190
|
end
|
|
193
191
|
|
|
194
192
|
# POST /v1/Assistants/{id}/Knowledge/{knowledgeId} — 204 No Content on success.
|
|
195
193
|
def attach(knowledge_id)
|
|
196
|
-
@transport.request(:post, "/v1/Assistants/#{@assistant_id}/Knowledge/#{knowledge_id}")
|
|
194
|
+
@transport.request(:post, "/v1/Assistants/#{encode_path_segment(@assistant_id)}/Knowledge/#{encode_path_segment(knowledge_id)}")
|
|
197
195
|
nil
|
|
198
196
|
end
|
|
199
197
|
|
|
200
198
|
# DELETE /v1/Assistants/{id}/Knowledge/{knowledgeId} — 204 No Content on success.
|
|
201
199
|
def detach(knowledge_id)
|
|
202
|
-
@transport.request(:delete, "/v1/Assistants/#{@assistant_id}/Knowledge/#{knowledge_id}")
|
|
200
|
+
@transport.request(:delete, "/v1/Assistants/#{encode_path_segment(@assistant_id)}/Knowledge/#{encode_path_segment(knowledge_id)}")
|
|
203
201
|
nil
|
|
204
202
|
end
|
|
205
203
|
end
|
|
206
204
|
|
|
207
205
|
# /v1/Assistants/{id}/Feedbacks — list + create.
|
|
208
206
|
class AssistantsV1AssistantFeedbacksScope
|
|
207
|
+
include V1Pages
|
|
208
|
+
include FieldMapping
|
|
209
209
|
CREATE_FIELDS = %i[session_id message_id score text].freeze
|
|
210
210
|
|
|
211
211
|
def initialize(transport, assistant_id)
|
|
@@ -217,34 +217,26 @@ module VoiceML
|
|
|
217
217
|
params = {}
|
|
218
218
|
params['PageSize'] = page_size unless page_size.nil?
|
|
219
219
|
AssistantsV1FeedbackList.new(
|
|
220
|
-
@transport.request(:get, "/v1/Assistants/#{@assistant_id}/Feedbacks", params: params)
|
|
220
|
+
@transport.request(:get, "/v1/Assistants/#{encode_path_segment(@assistant_id)}/Feedbacks", params: params)
|
|
221
221
|
)
|
|
222
222
|
end
|
|
223
223
|
|
|
224
224
|
def create(session_id:, **kwargs)
|
|
225
225
|
kwargs[:session_id] = session_id
|
|
226
226
|
AssistantsV1Feedback.from_hash(
|
|
227
|
-
@transport.request(:post, "/v1/Assistants/#{@assistant_id}/Feedbacks",
|
|
228
|
-
json:
|
|
227
|
+
@transport.request(:post, "/v1/Assistants/#{encode_path_segment(@assistant_id)}/Feedbacks",
|
|
228
|
+
json: json_params(CREATE_FIELDS, kwargs))
|
|
229
229
|
)
|
|
230
230
|
end
|
|
231
231
|
|
|
232
232
|
private
|
|
233
233
|
|
|
234
|
-
def build_json(keys, kwargs)
|
|
235
|
-
out = {}
|
|
236
|
-
keys.each do |k|
|
|
237
|
-
v = kwargs[k]
|
|
238
|
-
next if v.nil?
|
|
239
|
-
|
|
240
|
-
out[k.to_s] = v
|
|
241
|
-
end
|
|
242
|
-
out
|
|
243
|
-
end
|
|
244
234
|
end
|
|
245
235
|
|
|
246
236
|
# /v1/Assistants/{id}/Messages — send (create) a message; returns the model's reply.
|
|
247
237
|
class AssistantsV1AssistantMessagesScope
|
|
238
|
+
include V1Pages
|
|
239
|
+
include FieldMapping
|
|
248
240
|
CREATE_FIELDS = %i[identity body session_id webhook mode].freeze
|
|
249
241
|
|
|
250
242
|
def initialize(transport, assistant_id)
|
|
@@ -256,23 +248,13 @@ module VoiceML
|
|
|
256
248
|
kwargs[:identity] = identity
|
|
257
249
|
kwargs[:body] = body
|
|
258
250
|
AssistantsV1SendMessageResponse.from_hash(
|
|
259
|
-
@transport.request(:post, "/v1/Assistants/#{@assistant_id}/Messages",
|
|
260
|
-
json:
|
|
251
|
+
@transport.request(:post, "/v1/Assistants/#{encode_path_segment(@assistant_id)}/Messages",
|
|
252
|
+
json: json_params(CREATE_FIELDS, kwargs))
|
|
261
253
|
)
|
|
262
254
|
end
|
|
263
255
|
|
|
264
256
|
private
|
|
265
257
|
|
|
266
|
-
def build_json(keys, kwargs)
|
|
267
|
-
out = {}
|
|
268
|
-
keys.each do |k|
|
|
269
|
-
v = kwargs[k]
|
|
270
|
-
next if v.nil?
|
|
271
|
-
|
|
272
|
-
out[k.to_s] = v
|
|
273
|
-
end
|
|
274
|
-
out
|
|
275
|
-
end
|
|
276
258
|
end
|
|
277
259
|
|
|
278
260
|
# ============================================================================
|
|
@@ -281,6 +263,8 @@ module VoiceML
|
|
|
281
263
|
# Fetch returns the ToolWithPolicies shape (policies inline).
|
|
282
264
|
# ============================================================================
|
|
283
265
|
class AssistantsV1ToolsResource
|
|
266
|
+
include V1Pages
|
|
267
|
+
include FieldMapping
|
|
284
268
|
CREATE_FIELDS = %i[name type enabled assistant_id description meta].freeze
|
|
285
269
|
UPDATE_FIELDS = %i[name type enabled description meta].freeze
|
|
286
270
|
|
|
@@ -300,37 +284,27 @@ module VoiceML
|
|
|
300
284
|
kwargs[:type] = type
|
|
301
285
|
kwargs[:enabled] = enabled
|
|
302
286
|
AssistantsV1Tool.from_hash(
|
|
303
|
-
@transport.request(:post, '/v1/Tools', json:
|
|
287
|
+
@transport.request(:post, '/v1/Tools', json: json_params(CREATE_FIELDS, kwargs))
|
|
304
288
|
)
|
|
305
289
|
end
|
|
306
290
|
|
|
307
291
|
def fetch(id)
|
|
308
|
-
AssistantsV1ToolWithPolicies.from_hash(@transport.request(:get, "/v1/Tools/#{id}"))
|
|
292
|
+
AssistantsV1ToolWithPolicies.from_hash(@transport.request(:get, "/v1/Tools/#{encode_path_segment(id)}"))
|
|
309
293
|
end
|
|
310
294
|
|
|
311
295
|
def update(id, **kwargs)
|
|
312
296
|
AssistantsV1Tool.from_hash(
|
|
313
|
-
@transport.request(:put, "/v1/Tools/#{id}", json:
|
|
297
|
+
@transport.request(:put, "/v1/Tools/#{encode_path_segment(id)}", json: json_params(UPDATE_FIELDS, kwargs))
|
|
314
298
|
)
|
|
315
299
|
end
|
|
316
300
|
|
|
317
301
|
def delete(id)
|
|
318
|
-
@transport.request(:delete, "/v1/Tools/#{id}")
|
|
302
|
+
@transport.request(:delete, "/v1/Tools/#{encode_path_segment(id)}")
|
|
319
303
|
nil
|
|
320
304
|
end
|
|
321
305
|
|
|
322
306
|
private
|
|
323
307
|
|
|
324
|
-
def build_json(keys, kwargs)
|
|
325
|
-
out = {}
|
|
326
|
-
keys.each do |k|
|
|
327
|
-
v = kwargs[k]
|
|
328
|
-
next if v.nil?
|
|
329
|
-
|
|
330
|
-
out[k.to_s] = v
|
|
331
|
-
end
|
|
332
|
-
out
|
|
333
|
-
end
|
|
334
308
|
end
|
|
335
309
|
|
|
336
310
|
# ============================================================================
|
|
@@ -338,6 +312,8 @@ module VoiceML
|
|
|
338
312
|
# `list` accepts an optional `assistant_id:` filter (wire name `AssistantId`).
|
|
339
313
|
# ============================================================================
|
|
340
314
|
class AssistantsV1KnowledgeResource
|
|
315
|
+
include V1Pages
|
|
316
|
+
include FieldMapping
|
|
341
317
|
CREATE_FIELDS = %i[name type assistant_id description embedding_model knowledge_source_details].freeze
|
|
342
318
|
UPDATE_FIELDS = %i[name type description embedding_model knowledge_source_details].freeze
|
|
343
319
|
|
|
@@ -356,37 +332,27 @@ module VoiceML
|
|
|
356
332
|
kwargs[:name] = name
|
|
357
333
|
kwargs[:type] = type
|
|
358
334
|
AssistantsV1Knowledge.from_hash(
|
|
359
|
-
@transport.request(:post, '/v1/Knowledge', json:
|
|
335
|
+
@transport.request(:post, '/v1/Knowledge', json: json_params(CREATE_FIELDS, kwargs))
|
|
360
336
|
)
|
|
361
337
|
end
|
|
362
338
|
|
|
363
339
|
def fetch(id)
|
|
364
|
-
AssistantsV1Knowledge.from_hash(@transport.request(:get, "/v1/Knowledge/#{id}"))
|
|
340
|
+
AssistantsV1Knowledge.from_hash(@transport.request(:get, "/v1/Knowledge/#{encode_path_segment(id)}"))
|
|
365
341
|
end
|
|
366
342
|
|
|
367
343
|
def update(id, **kwargs)
|
|
368
344
|
AssistantsV1Knowledge.from_hash(
|
|
369
|
-
@transport.request(:put, "/v1/Knowledge/#{id}", json:
|
|
345
|
+
@transport.request(:put, "/v1/Knowledge/#{encode_path_segment(id)}", json: json_params(UPDATE_FIELDS, kwargs))
|
|
370
346
|
)
|
|
371
347
|
end
|
|
372
348
|
|
|
373
349
|
def delete(id)
|
|
374
|
-
@transport.request(:delete, "/v1/Knowledge/#{id}")
|
|
350
|
+
@transport.request(:delete, "/v1/Knowledge/#{encode_path_segment(id)}")
|
|
375
351
|
nil
|
|
376
352
|
end
|
|
377
353
|
|
|
378
354
|
private
|
|
379
355
|
|
|
380
|
-
def build_json(keys, kwargs)
|
|
381
|
-
out = {}
|
|
382
|
-
keys.each do |k|
|
|
383
|
-
v = kwargs[k]
|
|
384
|
-
next if v.nil?
|
|
385
|
-
|
|
386
|
-
out[k.to_s] = v
|
|
387
|
-
end
|
|
388
|
-
out
|
|
389
|
-
end
|
|
390
356
|
end
|
|
391
357
|
|
|
392
358
|
# ============================================================================
|
|
@@ -413,6 +379,8 @@ module VoiceML
|
|
|
413
379
|
|
|
414
380
|
# /v1/Knowledge/{id}/Status — read-only ingestion status snapshot.
|
|
415
381
|
class AssistantsV1KnowledgeStatusScope
|
|
382
|
+
include V1Pages
|
|
383
|
+
include FieldMapping
|
|
416
384
|
def initialize(transport, knowledge_id)
|
|
417
385
|
@transport = transport
|
|
418
386
|
@knowledge_id = knowledge_id
|
|
@@ -420,13 +388,15 @@ module VoiceML
|
|
|
420
388
|
|
|
421
389
|
def fetch
|
|
422
390
|
AssistantsV1KnowledgeStatus.from_hash(
|
|
423
|
-
@transport.request(:get, "/v1/Knowledge/#{@knowledge_id}/Status")
|
|
391
|
+
@transport.request(:get, "/v1/Knowledge/#{encode_path_segment(@knowledge_id)}/Status")
|
|
424
392
|
)
|
|
425
393
|
end
|
|
426
394
|
end
|
|
427
395
|
|
|
428
396
|
# /v1/Knowledge/{id}/Chunks — paged list of indexed chunks.
|
|
429
397
|
class AssistantsV1KnowledgeChunksScope
|
|
398
|
+
include V1Pages
|
|
399
|
+
include FieldMapping
|
|
430
400
|
def initialize(transport, knowledge_id)
|
|
431
401
|
@transport = transport
|
|
432
402
|
@knowledge_id = knowledge_id
|
|
@@ -436,7 +406,7 @@ module VoiceML
|
|
|
436
406
|
params = {}
|
|
437
407
|
params['PageSize'] = page_size unless page_size.nil?
|
|
438
408
|
AssistantsV1KnowledgeChunkList.new(
|
|
439
|
-
@transport.request(:get, "/v1/Knowledge/#{@knowledge_id}/Chunks", params: params)
|
|
409
|
+
@transport.request(:get, "/v1/Knowledge/#{encode_path_segment(@knowledge_id)}/Chunks", params: params)
|
|
440
410
|
)
|
|
441
411
|
end
|
|
442
412
|
end
|
|
@@ -445,6 +415,8 @@ module VoiceML
|
|
|
445
415
|
# /v1/Sessions — list + fetch on the top-level Session resource.
|
|
446
416
|
# ============================================================================
|
|
447
417
|
class AssistantsV1SessionsResource
|
|
418
|
+
include V1Pages
|
|
419
|
+
include FieldMapping
|
|
448
420
|
def initialize(transport)
|
|
449
421
|
@transport = transport
|
|
450
422
|
end
|
|
@@ -456,7 +428,7 @@ module VoiceML
|
|
|
456
428
|
end
|
|
457
429
|
|
|
458
430
|
def fetch(id)
|
|
459
|
-
AssistantsV1Session.from_hash(@transport.request(:get, "/v1/Sessions/#{id}"))
|
|
431
|
+
AssistantsV1Session.from_hash(@transport.request(:get, "/v1/Sessions/#{encode_path_segment(id)}"))
|
|
460
432
|
end
|
|
461
433
|
end
|
|
462
434
|
|
|
@@ -475,6 +447,8 @@ module VoiceML
|
|
|
475
447
|
end
|
|
476
448
|
|
|
477
449
|
class AssistantsV1SessionMessagesScope
|
|
450
|
+
include V1Pages
|
|
451
|
+
include FieldMapping
|
|
478
452
|
def initialize(transport, session_id)
|
|
479
453
|
@transport = transport
|
|
480
454
|
@session_id = session_id
|
|
@@ -484,7 +458,7 @@ module VoiceML
|
|
|
484
458
|
params = {}
|
|
485
459
|
params['PageSize'] = page_size unless page_size.nil?
|
|
486
460
|
AssistantsV1MessageList.new(
|
|
487
|
-
@transport.request(:get, "/v1/Sessions/#{@session_id}/Messages", params: params)
|
|
461
|
+
@transport.request(:get, "/v1/Sessions/#{encode_path_segment(@session_id)}/Messages", params: params)
|
|
488
462
|
)
|
|
489
463
|
end
|
|
490
464
|
end
|
|
@@ -493,6 +467,8 @@ module VoiceML
|
|
|
493
467
|
# /v1/Policies — read-only list, filterable by ToolId/KnowledgeId.
|
|
494
468
|
# ============================================================================
|
|
495
469
|
class AssistantsV1PoliciesResource
|
|
470
|
+
include V1Pages
|
|
471
|
+
include FieldMapping
|
|
496
472
|
def initialize(transport)
|
|
497
473
|
@transport = transport
|
|
498
474
|
end
|
|
@@ -1,38 +1,160 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
3
5
|
module VoiceML
|
|
6
|
+
# @api private
|
|
7
|
+
# Kwarg-to-wire-name mapping shared by every resource that takes `**kwargs`.
|
|
8
|
+
# Raises `ArgumentError` for kwargs outside the field map, so a typo
|
|
9
|
+
# (`machine_detecton:`) fails loudly instead of being silently dropped.
|
|
10
|
+
module FieldMapping
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
# Translate snake_case Ruby kwargs to the form/query field names the server
|
|
14
|
+
# expects. `nil` values are dropped; booleans and dates are formatted inside
|
|
15
|
+
# Transport.
|
|
16
|
+
def form_params(map, kwargs)
|
|
17
|
+
unknown = kwargs.keys - map.values
|
|
18
|
+
unless unknown.empty?
|
|
19
|
+
raise ArgumentError, "unknown keyword(s): #{unknown.map(&:inspect).sort.join(', ')}; " \
|
|
20
|
+
"expected one of #{map.values.map(&:inspect).sort.join(', ')}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
out = {}
|
|
24
|
+
map.each do |wire_name, ruby_key|
|
|
25
|
+
value = kwargs[ruby_key]
|
|
26
|
+
next if value.nil?
|
|
27
|
+
|
|
28
|
+
out[wire_name] = value
|
|
29
|
+
end
|
|
30
|
+
out
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Translate a snake_case kwargs subset for JSON bodies (Assistants v1 keeps
|
|
34
|
+
# snake_case wire names). Same strictness as `form_params`.
|
|
35
|
+
def json_params(keys, kwargs)
|
|
36
|
+
unknown = kwargs.keys - keys
|
|
37
|
+
unless unknown.empty?
|
|
38
|
+
raise ArgumentError, "unknown keyword(s): #{unknown.map(&:inspect).sort.join(', ')}; " \
|
|
39
|
+
"expected one of #{keys.map(&:inspect).sort.join(', ')}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
out = {}
|
|
43
|
+
keys.each do |key|
|
|
44
|
+
value = kwargs[key]
|
|
45
|
+
next if value.nil?
|
|
46
|
+
|
|
47
|
+
out[key.to_s] = value
|
|
48
|
+
end
|
|
49
|
+
out
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Percent-encode one caller-supplied path segment per RFC 3986: keep the
|
|
53
|
+
# unreserved set (`A-Z a-z 0-9 - . _ ~`) and encode every other byte as
|
|
54
|
+
# `%XX` (UTF-8), so `+` becomes `%2B`, a space `%20`, `/` `%2F`, `?` `%3F`,
|
|
55
|
+
# `#` `%23` and `%` `%25`. Applied once per segment — never to a full path.
|
|
56
|
+
def encode_path_segment(segment)
|
|
57
|
+
segment.to_s.b.gsub(/[^A-Za-z0-9\-._~]/) { |byte| format('%%%02X', byte.ord) }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def page_url(link, absolute: false)
|
|
61
|
+
base = URI.parse(@transport.base_url)
|
|
62
|
+
uri = URI.parse(link)
|
|
63
|
+
raise ArgumentError, 'expected an absolute next_page_url' if absolute && !uri.absolute?
|
|
64
|
+
|
|
65
|
+
uri = URI.join("#{base.scheme}://#{base.authority}/", link) unless uri.absolute?
|
|
66
|
+
unless uri.scheme == base.scheme && uri.host == base.host && uri.port == base.port && !uri.userinfo
|
|
67
|
+
raise ArgumentError, 'next page must stay on the configured product origin'
|
|
68
|
+
end
|
|
69
|
+
uri.to_s
|
|
70
|
+
rescue URI::Error, ArgumentError => e
|
|
71
|
+
raise ConnectionError.new("invalid next-page link: #{e.message}", status_code: 0)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
4
75
|
# @api private
|
|
5
76
|
# Mixin holding a `Transport` reference and helpers for AccountSid-scoped pathing.
|
|
6
77
|
class BaseResource
|
|
78
|
+
include FieldMapping
|
|
79
|
+
|
|
7
80
|
def initialize(transport)
|
|
8
81
|
@transport = transport
|
|
9
82
|
end
|
|
10
83
|
|
|
84
|
+
# Fetch the page a list envelope links to via `next_page_uri`, verbatim:
|
|
85
|
+
# the URI (path + query, resolved against the transport's base host) is
|
|
86
|
+
# sent as-is, never re-synthesised from a page counter.
|
|
87
|
+
#
|
|
88
|
+
# @return [Object, nil] the next page's envelope (same class as the given
|
|
89
|
+
# one), or `nil` when the envelope has no next page.
|
|
90
|
+
def next_page(list)
|
|
91
|
+
uri = list.respond_to?(:next_page_uri) ? list.next_page_uri : nil
|
|
92
|
+
return nil if uri.nil? || uri.empty?
|
|
93
|
+
|
|
94
|
+
list.class.new(@transport.request(:get, page_url(uri)))
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# A redacted dump: never includes credentials via the transport.
|
|
98
|
+
def inspect
|
|
99
|
+
"#<#{self.class.name}>"
|
|
100
|
+
end
|
|
101
|
+
alias to_s inspect
|
|
102
|
+
|
|
11
103
|
private
|
|
12
104
|
|
|
13
105
|
# Build a URL under `/2010-04-01/Accounts/{AccountSid}/...`. Caller passes path segments
|
|
14
|
-
# (e.g. `"Calls"`, sid, `"Recordings"`). Empty segments are skipped;
|
|
15
|
-
#
|
|
106
|
+
# (e.g. `"Calls"`, sid, `"Recordings"`). Empty segments are skipped; every segment is
|
|
107
|
+
# percent-encoded as one RFC 3986 path segment.
|
|
16
108
|
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
109
|
+
# Every REST endpoint resolves under its `.json` form. Pass `suffix: ''` to opt out —
|
|
110
|
+
# used by `.wav` audio fetches, export downloads and any caller that needs to append a
|
|
111
|
+
# different extension.
|
|
20
112
|
def path(*parts, suffix: '.json')
|
|
21
|
-
tail = parts.compact.reject { |p| p.to_s.empty? }.join('/')
|
|
22
|
-
"/2010-04-01/Accounts/#{@transport.account_sid}/#{tail}#{suffix}"
|
|
113
|
+
tail = parts.compact.reject { |p| p.to_s.empty? }.map { |p| encode_path_segment(p) }.join('/')
|
|
114
|
+
"/2010-04-01/Accounts/#{encode_path_segment(@transport.account_sid)}/#{tail}#{suffix}"
|
|
23
115
|
end
|
|
116
|
+
end
|
|
24
117
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
118
|
+
# @api private
|
|
119
|
+
# `next_page` / `each_page` support for `/v1` list envelopes, which page via
|
|
120
|
+
# an absolute `meta.next_page_url` instead of a relative `next_page_uri`.
|
|
121
|
+
# The URL is only followed when its scheme and host equal the resource's
|
|
122
|
+
# configured base, so credentials are never sent to a third-party host.
|
|
123
|
+
module V1Pages
|
|
124
|
+
include FieldMapping
|
|
125
|
+
# Follow `meta.next_page_url` from a list envelope.
|
|
126
|
+
#
|
|
127
|
+
# @return [Object, nil] the next page's envelope (same class as the given
|
|
128
|
+
# one), or `nil` when the envelope has no next page.
|
|
129
|
+
def next_page(list)
|
|
130
|
+
url = list.respond_to?(:next_page_url) ? list.next_page_url : nil
|
|
131
|
+
return nil if url.nil? || url.empty?
|
|
32
132
|
|
|
33
|
-
|
|
133
|
+
list.class.new(@transport.request(:get, page_url(url, absolute: true)))
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Yield every item of every page of a `/v1` list envelope, fetching pages
|
|
137
|
+
# lazily. Returns an Enumerator when called without a block; stopping
|
|
138
|
+
# early makes no further requests.
|
|
139
|
+
def each_page(list, &block)
|
|
140
|
+
return enum_for(:each_page, list) unless block
|
|
141
|
+
|
|
142
|
+
page = list
|
|
143
|
+
loop do
|
|
144
|
+
items = v1_items(page)
|
|
145
|
+
items.each(&block)
|
|
146
|
+
nxt = next_page(page)
|
|
147
|
+
break if nxt.nil?
|
|
148
|
+
|
|
149
|
+
page = nxt
|
|
34
150
|
end
|
|
35
|
-
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
private
|
|
154
|
+
|
|
155
|
+
def v1_items(list)
|
|
156
|
+
key = list.to_h.keys.find { |k| list.to_h[k].is_a?(Array) }
|
|
157
|
+
key && list.respond_to?(key) ? list.public_send(key) : []
|
|
36
158
|
end
|
|
37
159
|
end
|
|
38
160
|
end
|