openai 0.106.0 → 0.108.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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +74 -0
  3. data/README.md +49 -1
  4. data/examples/chat/tool_runner.rb +33 -0
  5. data/lib/openai/client.rb +2 -2
  6. data/lib/openai/helpers/chat/tool_runner.rb +259 -0
  7. data/lib/openai/helpers/live/websocket.rb +12 -141
  8. data/lib/openai/helpers/local_audio/process.rb +13 -3
  9. data/lib/openai/helpers/models/embedding.rb +42 -0
  10. data/lib/openai/helpers/realtime/connection.rb +22 -5
  11. data/lib/openai/helpers/realtime/recovery.rb +19 -7
  12. data/lib/openai/helpers/realtime/translation.rb +37 -169
  13. data/lib/openai/helpers/realtime/unknown_server_event.rb +5 -12
  14. data/lib/openai/helpers/responses_websocket/connection.rb +56 -35
  15. data/lib/openai/helpers/responses_websocket/incremental.rb +5 -1
  16. data/lib/openai/helpers/responses_websocket/session.rb +11 -4
  17. data/lib/openai/helpers/responses_websocket/unknown_server_event.rb +2 -14
  18. data/lib/openai/helpers/streaming/chat_completion_resource.rb +52 -0
  19. data/lib/openai/helpers/websocket/async_websocket_transport.rb +8 -6
  20. data/lib/openai/helpers/websocket/client_request.rb +1 -1
  21. data/lib/openai/helpers/websocket/connection.rb +21 -10
  22. data/lib/openai/helpers/websocket/connection_manager.rb +2 -1
  23. data/lib/openai/helpers/websocket/protocol.rb +160 -0
  24. data/lib/openai/helpers/websocket/typed_connection.rb +22 -16
  25. data/lib/openai/helpers/websocket/typed_resource.rb +15 -0
  26. data/lib/openai/internal/transport/base_client.rb +1 -1
  27. data/lib/openai/models/admin/organization/usage_audio_speeches_response.rb +16 -5
  28. data/lib/openai/models/admin/organization/usage_audio_transcriptions_response.rb +16 -5
  29. data/lib/openai/models/admin/organization/usage_code_interpreter_sessions_response.rb +16 -5
  30. data/lib/openai/models/admin/organization/usage_completions_response.rb +16 -5
  31. data/lib/openai/models/admin/organization/usage_costs_response.rb +16 -5
  32. data/lib/openai/models/admin/organization/usage_decisions_response.rb +14 -3
  33. data/lib/openai/models/admin/organization/usage_embeddings_response.rb +16 -5
  34. data/lib/openai/models/admin/organization/usage_file_search_calls_response.rb +16 -5
  35. data/lib/openai/models/admin/organization/usage_images_response.rb +16 -5
  36. data/lib/openai/models/admin/organization/usage_moderations_response.rb +16 -5
  37. data/lib/openai/models/admin/organization/usage_vector_stores_response.rb +16 -5
  38. data/lib/openai/models/admin/organization/usage_web_search_calls_response.rb +16 -5
  39. data/lib/openai/models/audio/voice_consent.rb +58 -0
  40. data/lib/openai/models/audio/voice_consent_create_params.rb +57 -0
  41. data/lib/openai/models/audio/voice_consent_delete_params.rb +22 -0
  42. data/lib/openai/models/audio/voice_consent_deleted.rb +34 -0
  43. data/lib/openai/models/audio/voice_consent_list_params.rb +42 -0
  44. data/lib/openai/models/audio/voice_consent_retrieve_params.rb +22 -0
  45. data/lib/openai/models/audio/voice_consent_update_params.rb +32 -0
  46. data/lib/openai/models/beta/beta_response_input_item.rb +10 -1
  47. data/lib/openai/models/responses/response_input_item.rb +10 -1
  48. data/lib/openai/resources/audio/voice_consents.rb +163 -0
  49. data/lib/openai/resources/audio.rb +5 -0
  50. data/lib/openai/version.rb +1 -1
  51. data/lib/openai.rb +9 -0
  52. data/rbi/openai/client.rbi +1 -8
  53. data/rbi/openai/helpers/chat/tool_runner.rbi +74 -0
  54. data/rbi/openai/helpers/realtime/translation.rbi +0 -5
  55. data/rbi/openai/helpers/realtime/unknown_server_event.rbi +6 -0
  56. data/rbi/openai/helpers/websocket.rbi +44 -6
  57. data/rbi/openai/internal/transport/base_client.rbi +2 -6
  58. data/rbi/openai/models/admin/organization/usage_audio_speeches_response.rbi +14 -2
  59. data/rbi/openai/models/admin/organization/usage_audio_transcriptions_response.rbi +14 -2
  60. data/rbi/openai/models/admin/organization/usage_code_interpreter_sessions_response.rbi +14 -2
  61. data/rbi/openai/models/admin/organization/usage_completions_response.rbi +14 -2
  62. data/rbi/openai/models/admin/organization/usage_costs_response.rbi +14 -2
  63. data/rbi/openai/models/admin/organization/usage_decisions_response.rbi +12 -0
  64. data/rbi/openai/models/admin/organization/usage_embeddings_response.rbi +14 -2
  65. data/rbi/openai/models/admin/organization/usage_file_search_calls_response.rbi +14 -2
  66. data/rbi/openai/models/admin/organization/usage_images_response.rbi +14 -2
  67. data/rbi/openai/models/admin/organization/usage_moderations_response.rbi +14 -2
  68. data/rbi/openai/models/admin/organization/usage_vector_stores_response.rbi +14 -2
  69. data/rbi/openai/models/admin/organization/usage_web_search_calls_response.rbi +14 -2
  70. data/rbi/openai/models/audio/voice_consent.rbi +86 -0
  71. data/rbi/openai/models/audio/voice_consent_create_params.rbi +92 -0
  72. data/rbi/openai/models/audio/voice_consent_delete_params.rbi +53 -0
  73. data/rbi/openai/models/audio/voice_consent_deleted.rbi +62 -0
  74. data/rbi/openai/models/audio/voice_consent_list_params.rbi +78 -0
  75. data/rbi/openai/models/audio/voice_consent_retrieve_params.rbi +53 -0
  76. data/rbi/openai/models/audio/voice_consent_update_params.rbi +62 -0
  77. data/rbi/openai/models/beta/beta_response_input_item.rbi +14 -1
  78. data/rbi/openai/models/response_format_json_schema.rbi +13 -11
  79. data/rbi/openai/models/responses/response_input_item.rbi +10 -1
  80. data/rbi/openai/resources/audio/voice_consents.rbi +108 -0
  81. data/rbi/openai/resources/audio.rbi +4 -0
  82. data/realtime.md +22 -3
  83. data/sig/openai/client.rbs +1 -1
  84. data/sig/openai/helpers/chat/tool_runner.rbs +48 -0
  85. data/sig/openai/helpers/realtime/translation.rbs +0 -2
  86. data/sig/openai/helpers/realtime/unknown_server_event.rbs +2 -0
  87. data/sig/openai/helpers/websocket.rbs +23 -6
  88. data/sig/openai/models/admin/organization/usage_audio_speeches_response.rbs +15 -5
  89. data/sig/openai/models/admin/organization/usage_audio_transcriptions_response.rbs +15 -5
  90. data/sig/openai/models/admin/organization/usage_code_interpreter_sessions_response.rbs +15 -5
  91. data/sig/openai/models/admin/organization/usage_completions_response.rbs +15 -5
  92. data/sig/openai/models/admin/organization/usage_costs_response.rbs +15 -5
  93. data/sig/openai/models/admin/organization/usage_decisions_response.rbs +11 -1
  94. data/sig/openai/models/admin/organization/usage_embeddings_response.rbs +15 -5
  95. data/sig/openai/models/admin/organization/usage_file_search_calls_response.rbs +15 -5
  96. data/sig/openai/models/admin/organization/usage_images_response.rbs +15 -5
  97. data/sig/openai/models/admin/organization/usage_moderations_response.rbs +15 -5
  98. data/sig/openai/models/admin/organization/usage_vector_stores_response.rbs +15 -5
  99. data/sig/openai/models/admin/organization/usage_web_search_calls_response.rbs +15 -5
  100. data/sig/openai/models/audio/voice_consent.rbs +57 -0
  101. data/sig/openai/models/audio/voice_consent_create_params.rbs +61 -0
  102. data/sig/openai/models/audio/voice_consent_delete_params.rbs +25 -0
  103. data/sig/openai/models/audio/voice_consent_deleted.rbs +31 -0
  104. data/sig/openai/models/audio/voice_consent_list_params.rbs +57 -0
  105. data/sig/openai/models/audio/voice_consent_retrieve_params.rbs +25 -0
  106. data/sig/openai/models/audio/voice_consent_update_params.rbs +36 -0
  107. data/sig/openai/models/beta/beta_response_input_item.rbs +8 -0
  108. data/sig/openai/models/responses/response_input_item.rbs +8 -3
  109. data/sig/openai/resources/audio/voice_consents.rbs +38 -0
  110. data/sig/openai/resources/audio.rbs +2 -0
  111. metadata +31 -1
@@ -0,0 +1,62 @@
1
+ # typed: strong
2
+
3
+ module OpenAI
4
+ module Models
5
+
6
+ module Audio
7
+
8
+ class VoiceConsentDeleted < OpenAI::Internal::Type::BaseModel
9
+
10
+ OrHash = T.type_alias do
11
+ T.any(
12
+ OpenAI::Audio::VoiceConsentDeleted,
13
+ OpenAI::Internal::AnyHash
14
+ )
15
+ end
16
+
17
+ # The consent recording identifier.
18
+ sig { returns(String) }
19
+ attr_accessor :id
20
+
21
+ sig { returns(T::Boolean) }
22
+ attr_accessor :deleted
23
+
24
+ sig { returns(Symbol) }
25
+ attr_accessor :object
26
+
27
+ sig do
28
+ params(
29
+
30
+ id: String,
31
+
32
+ deleted: T::Boolean,
33
+
34
+ object: Symbol
35
+ )
36
+ .returns(T.attached_class)
37
+ end
38
+ def self.new(
39
+
40
+ # The consent recording identifier.
41
+ id:,
42
+
43
+ deleted:,
44
+
45
+ object: :"audio.voice_consent"
46
+ )
47
+ end
48
+
49
+ sig do
50
+ override.returns(
51
+ {id: String, deleted: T::Boolean, object: Symbol}
52
+ )
53
+ end
54
+ def to_hash
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,78 @@
1
+ # typed: strong
2
+
3
+ module OpenAI
4
+ module Models
5
+
6
+ module Audio
7
+
8
+ class VoiceConsentListParams < OpenAI::Internal::Type::BaseModel
9
+
10
+ extend OpenAI::Internal::Type::RequestParameters::Converter
11
+ include OpenAI::Internal::Type::RequestParameters
12
+
13
+ OrHash = T.type_alias do
14
+ T.any(
15
+ OpenAI::Audio::VoiceConsentListParams,
16
+ OpenAI::Internal::AnyHash
17
+ )
18
+ end
19
+
20
+ # A cursor for use in pagination. `after` is an object ID that defines your place
21
+ # in the list. For instance, if you make a list request and receive 100 objects,
22
+ # ending with obj_foo, your subsequent call can include after=obj_foo in order to
23
+ # fetch the next page of the list.
24
+ sig { returns(T.nilable(String)) }
25
+ attr_reader :after
26
+
27
+ sig { params(after: String).void }
28
+ attr_writer :after
29
+
30
+ # A limit on the number of objects to be returned. Limit can range between 1 and
31
+ # 100, and the default is 20.
32
+ sig { returns(T.nilable(Integer)) }
33
+ attr_reader :limit
34
+
35
+ sig { params(limit: Integer).void }
36
+ attr_writer :limit
37
+
38
+ sig do
39
+ params(
40
+
41
+ after: String,
42
+
43
+ limit: Integer,
44
+
45
+ request_options: OpenAI::RequestOptions::OrHash
46
+ )
47
+ .returns(T.attached_class)
48
+ end
49
+ def self.new(
50
+
51
+ # A cursor for use in pagination. `after` is an object ID that defines your place
52
+ # in the list. For instance, if you make a list request and receive 100 objects,
53
+ # ending with obj_foo, your subsequent call can include after=obj_foo in order to
54
+ # fetch the next page of the list.
55
+ after: nil,
56
+
57
+ # A limit on the number of objects to be returned. Limit can range between 1 and
58
+ # 100, and the default is 20.
59
+ limit: nil,
60
+
61
+ request_options: {}
62
+ )
63
+ end
64
+
65
+ sig do
66
+ override.returns(
67
+ {after: String, limit: Integer, request_options: OpenAI::RequestOptions}
68
+ )
69
+ end
70
+ def to_hash
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,53 @@
1
+ # typed: strong
2
+
3
+ module OpenAI
4
+ module Models
5
+
6
+ module Audio
7
+
8
+ class VoiceConsentRetrieveParams < OpenAI::Internal::Type::BaseModel
9
+
10
+ extend OpenAI::Internal::Type::RequestParameters::Converter
11
+ include OpenAI::Internal::Type::RequestParameters
12
+
13
+ OrHash = T.type_alias do
14
+ T.any(
15
+ OpenAI::Audio::VoiceConsentRetrieveParams,
16
+ OpenAI::Internal::AnyHash
17
+ )
18
+ end
19
+
20
+ sig { returns(String) }
21
+ attr_accessor :consent_id
22
+
23
+ sig do
24
+ params(
25
+
26
+ consent_id: String,
27
+
28
+ request_options: OpenAI::RequestOptions::OrHash
29
+ )
30
+ .returns(T.attached_class)
31
+ end
32
+ def self.new(
33
+
34
+ consent_id:,
35
+
36
+ request_options: {}
37
+ )
38
+ end
39
+
40
+ sig do
41
+ override.returns(
42
+ {consent_id: String, request_options: OpenAI::RequestOptions}
43
+ )
44
+ end
45
+ def to_hash
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,62 @@
1
+ # typed: strong
2
+
3
+ module OpenAI
4
+ module Models
5
+
6
+ module Audio
7
+
8
+ class VoiceConsentUpdateParams < OpenAI::Internal::Type::BaseModel
9
+
10
+ extend OpenAI::Internal::Type::RequestParameters::Converter
11
+ include OpenAI::Internal::Type::RequestParameters
12
+
13
+ OrHash = T.type_alias do
14
+ T.any(
15
+ OpenAI::Audio::VoiceConsentUpdateParams,
16
+ OpenAI::Internal::AnyHash
17
+ )
18
+ end
19
+
20
+ sig { returns(String) }
21
+ attr_accessor :consent_id
22
+
23
+ # The updated label for this consent recording.
24
+ sig { returns(String) }
25
+ attr_accessor :name
26
+
27
+ sig do
28
+ params(
29
+
30
+ consent_id: String,
31
+
32
+ name: String,
33
+
34
+ request_options: OpenAI::RequestOptions::OrHash
35
+ )
36
+ .returns(T.attached_class)
37
+ end
38
+ def self.new(
39
+
40
+ consent_id:,
41
+
42
+ # The updated label for this consent recording.
43
+ name:,
44
+
45
+ request_options: {}
46
+ )
47
+ end
48
+
49
+ sig do
50
+ override.returns(
51
+ {consent_id: String, name: String, request_options: OpenAI::RequestOptions}
52
+ )
53
+ end
54
+ def to_hash
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+ end
@@ -5130,6 +5130,10 @@ module OpenAI
5130
5130
  sig { returns(Symbol) }
5131
5131
  attr_accessor :type
5132
5132
 
5133
+ # The unique ID of this compaction trigger.
5134
+ sig { returns(T.nilable(String)) }
5135
+ attr_accessor :id
5136
+
5133
5137
  # The agent that produced this item.
5134
5138
  sig { returns(T.nilable(OpenAI::Beta::BetaResponseInputItem::CompactionTrigger::Agent)) }
5135
5139
  attr_reader :agent
@@ -5141,6 +5145,8 @@ module OpenAI
5141
5145
  sig do
5142
5146
  params(
5143
5147
 
5148
+ id: T.nilable(String),
5149
+
5144
5150
  agent: T.nilable(OpenAI::Beta::BetaResponseInputItem::CompactionTrigger::Agent::OrHash),
5145
5151
 
5146
5152
  type: Symbol
@@ -5149,6 +5155,9 @@ module OpenAI
5149
5155
  end
5150
5156
  def self.new(
5151
5157
 
5158
+ # The unique ID of this compaction trigger.
5159
+ id: nil,
5160
+
5152
5161
  # The agent that produced this item.
5153
5162
  agent: nil,
5154
5163
 
@@ -5160,7 +5169,11 @@ module OpenAI
5160
5169
 
5161
5170
  sig do
5162
5171
  override.returns(
5163
- {type: Symbol, agent: T.nilable(OpenAI::Beta::BetaResponseInputItem::CompactionTrigger::Agent)}
5172
+ {
5173
+ type: Symbol,
5174
+ id: T.nilable(String),
5175
+ agent: T.nilable(OpenAI::Beta::BetaResponseInputItem::CompactionTrigger::Agent)
5176
+ }
5164
5177
  )
5165
5178
  end
5166
5179
  def to_hash
@@ -2,24 +2,25 @@
2
2
 
3
3
  module OpenAI
4
4
  module Models
5
+
5
6
  class ResponseFormatJSONSchema < OpenAI::Internal::Type::BaseModel
7
+
6
8
  OrHash = T.type_alias do
7
- T.any(OpenAI::ResponseFormatJSONSchema, OpenAI::Internal::AnyHash)
9
+ T.any(
10
+ OpenAI::ResponseFormatJSONSchema,
11
+ OpenAI::Internal::AnyHash
12
+ )
8
13
  end
9
14
 
10
15
  # Structured Outputs configuration options, including a JSON Schema.
11
- sig do
16
+ sig {
12
17
  returns(
13
- T.any(
14
- OpenAI::ResponseFormatJSONSchema::JSONSchema::OrHash,
15
- OpenAI::StructuredOutput::JsonSchemaConverter
16
- )
18
+ T.any(OpenAI::ResponseFormatJSONSchema::JSONSchema::OrHash, OpenAI::StructuredOutput::JsonSchemaConverter)
17
19
  )
18
- end
19
-
20
+ }
20
21
  attr_reader :json_schema
21
22
 
22
- sig do
23
+ sig {
23
24
  params(
24
25
  json_schema: T.any(
25
26
  OpenAI::ResponseFormatJSONSchema::JSONSchema::OrHash,
@@ -27,8 +28,7 @@ module OpenAI
27
28
  )
28
29
  )
29
30
  .void
30
- end
31
-
31
+ }
32
32
  attr_writer :json_schema
33
33
 
34
34
  # The type of response format being defined. Always `json_schema`.
@@ -40,10 +40,12 @@ module OpenAI
40
40
  # [Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs).
41
41
  sig do
42
42
  params(
43
+
43
44
  json_schema: T.any(
44
45
  OpenAI::ResponseFormatJSONSchema::JSONSchema::OrHash,
45
46
  OpenAI::StructuredOutput::JsonSchemaConverter
46
47
  ),
48
+
47
49
  type: Symbol
48
50
  )
49
51
  .returns(T.attached_class)
@@ -3433,16 +3433,25 @@ module OpenAI
3433
3433
  sig { returns(Symbol) }
3434
3434
  attr_accessor :type
3435
3435
 
3436
+ # The unique ID of this compaction trigger.
3437
+ sig { returns(T.nilable(String)) }
3438
+ attr_accessor :id
3439
+
3436
3440
  # Compacts the current context. Must be the final input item.
3437
3441
  sig do
3438
3442
  params(
3439
3443
 
3444
+ id: T.nilable(String),
3445
+
3440
3446
  type: Symbol
3441
3447
  )
3442
3448
  .returns(T.attached_class)
3443
3449
  end
3444
3450
  def self.new(
3445
3451
 
3452
+ # The unique ID of this compaction trigger.
3453
+ id: nil,
3454
+
3446
3455
  # The type of the item. Always `compaction_trigger`.
3447
3456
 
3448
3457
  type: :compaction_trigger
@@ -3451,7 +3460,7 @@ module OpenAI
3451
3460
 
3452
3461
  sig do
3453
3462
  override.returns(
3454
- {type: Symbol}
3463
+ {type: Symbol, id: T.nilable(String)}
3455
3464
  )
3456
3465
  end
3457
3466
  def to_hash
@@ -0,0 +1,108 @@
1
+ # typed: strong
2
+
3
+ module OpenAI
4
+ module Resources
5
+
6
+ class Audio
7
+
8
+ # Turn audio into text or text into audio.
9
+ class VoiceConsents
10
+
11
+ # Upload a voice consent recording.
12
+ sig {
13
+ params(
14
+ language: String,
15
+ name: String,
16
+ recording: OpenAI::Internal::FileInput,
17
+ request_options: OpenAI::RequestOptions::OrHash
18
+ )
19
+ .returns(OpenAI::Audio::VoiceConsent)
20
+ }
21
+ def create(
22
+ # The BCP 47 language tag for the consent phrase (for example, `en-US`).
23
+ language:,
24
+ # The label to use for this consent recording.
25
+ name:,
26
+ # The consent audio recording file. Maximum size is 10 MiB.
27
+ #
28
+ # Supported MIME types: `audio/mpeg`, `audio/wav`, `audio/x-wav`, `audio/ogg`,
29
+ # `audio/aac`, `audio/flac`, `audio/webm`, `audio/mp4`.
30
+ #
31
+ # `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
32
+ # metadata. Use `OpenAI::FilePart` when you need to override the filename or
33
+ # content type.
34
+ recording:,
35
+ request_options: {}
36
+ )
37
+ end
38
+
39
+ # Retrieves a voice consent recording.
40
+ sig {
41
+ params(consent_id: String, request_options: OpenAI::RequestOptions::OrHash).returns(
42
+ OpenAI::Audio::VoiceConsent
43
+ )
44
+ }
45
+ def retrieve(
46
+ # The ID of the consent recording to retrieve.
47
+ consent_id,
48
+ request_options: {}
49
+ )
50
+ end
51
+
52
+ # Updates a voice consent recording (metadata only).
53
+ sig {
54
+ params(consent_id: String, name: String, request_options: OpenAI::RequestOptions::OrHash).returns(
55
+ OpenAI::Audio::VoiceConsent
56
+ )
57
+ }
58
+ def update(
59
+ # The ID of the consent recording to update.
60
+ consent_id,
61
+ # The updated label for this consent recording.
62
+ name:,
63
+ request_options: {}
64
+ )
65
+ end
66
+
67
+ # Returns a list of voice consent recordings.
68
+ sig {
69
+ params(after: String, limit: Integer, request_options: OpenAI::RequestOptions::OrHash).returns(
70
+ OpenAI::Internal::CursorPage[OpenAI::Audio::VoiceConsent]
71
+ )
72
+ }
73
+ def list(
74
+ # A cursor for use in pagination. `after` is an object ID that defines your place
75
+ # in the list. For instance, if you make a list request and receive 100 objects,
76
+ # ending with obj_foo, your subsequent call can include after=obj_foo in order to
77
+ # fetch the next page of the list.
78
+ after: nil,
79
+ # A limit on the number of objects to be returned. Limit can range between 1 and
80
+ # 100, and the default is 20.
81
+ limit: nil,
82
+ request_options: {}
83
+ )
84
+ end
85
+
86
+ # Deletes a voice consent recording.
87
+ sig {
88
+ params(consent_id: String, request_options: OpenAI::RequestOptions::OrHash).returns(
89
+ OpenAI::Audio::VoiceConsentDeleted
90
+ )
91
+ }
92
+ def delete(
93
+ # The ID of the consent recording to delete.
94
+ consent_id,
95
+ request_options: {}
96
+ )
97
+ end
98
+
99
+ # @api private
100
+ sig { params(client: OpenAI::Client).returns(T.attached_class) }
101
+ def self.new(client:)
102
+ end
103
+ end
104
+
105
+ end
106
+
107
+ end
108
+ end
@@ -21,6 +21,10 @@ module OpenAI
21
21
  sig { returns(OpenAI::Resources::Audio::Voices) }
22
22
  attr_reader :voices
23
23
 
24
+ # Turn audio into text or text into audio.
25
+ sig { returns(OpenAI::Resources::Audio::VoiceConsents) }
26
+ attr_reader :voice_consents
27
+
24
28
  # @api private
25
29
  sig { params(client: OpenAI::Client).returns(T.attached_class) }
26
30
  def self.new(client:)
data/realtime.md CHANGED
@@ -468,6 +468,8 @@ Malformed known events raise `OpenAI::Errors::RealtimeProtocolError`. A valid
468
468
  JSON object with a newer, unknown event discriminator is returned as
469
469
  `OpenAI::Realtime::UnknownServerEvent`, preserving its deeply frozen payload so
470
470
  an additive service event does not terminate an otherwise healthy session.
471
+ Its `inspect` and `to_s` output omits remote values. Access `type`, `data`, or
472
+ `to_h` explicitly when those values are needed.
471
473
 
472
474
  ```ruby
473
475
  connection.each do |event|
@@ -495,6 +497,11 @@ Connection and protocol failures use distinct error classes:
495
497
  - `OpenAI::Errors::RealtimeProtocolError` exposes the invalid raw `data` and
496
498
  original `cause`.
497
499
 
500
+ For these connection and protocol errors, default rendering, including
501
+ `full_message`, suppresses native cause chains, including exceptions active when
502
+ an SDK state check fails. Explicit `data` and `cause` access can expose remote
503
+ payloads or credentials; sanitize these values before logging or sharing them.
504
+
498
505
  The configured request timeout bounds WebSocket negotiation. It does not become
499
506
  an idle-session deadline after the connection is established.
500
507
 
@@ -595,6 +602,18 @@ The examples in this guide cover local function calling, image input, and MCP
595
602
  approval through the generic Realtime connection API, alongside generated
596
603
  WebRTC/SDP call creation and sideband control of existing WebRTC and SIP calls.
597
604
  Continuous microphone capture, concurrent live captioning, full-duplex
598
- conversation, SIP call-ownership orchestration, and translation connections
599
- remain out of scope. Existing generated HTTP resources remain
600
- generated-code-owned.
605
+ conversation, and SIP call-ownership orchestration are outside this guide's
606
+ scope.
607
+
608
+ ## Translation connections
609
+
610
+ The SDK also supports the separate Translation WebSocket protocol through
611
+ `client.realtime.connect_translation(model: ...) { |connection| ... }`.
612
+ It uses Translation event types rather than the Realtime events shown above.
613
+ See the [Translation connection helper](lib/openai/helpers/realtime/translation.rb)
614
+ and [server event types](lib/openai/models/realtime/realtime_translation_server_event.rb).
615
+
616
+ After sending input, call `connection.finish(timeout: ...)` with a block to
617
+ consume the remaining events through `session.closed`. Finish calls must be
618
+ sequential, with no competing reader. Keep the connection inside its opening
619
+ block so the SDK can clean it up when the block exits.
@@ -75,7 +75,7 @@ module OpenAI
75
75
  attr_reader videos: OpenAI::Resources::Videos
76
76
 
77
77
  private def auth_headers: (
78
- security: { :bearer_auth? => bool, :admin_api_key_auth? => bool }
78
+ security: { ?bearer_auth: bool, ?admin_api_key_auth: bool }
79
79
  ) -> ::Hash[String, String]
80
80
 
81
81
  private def bearer_auth: -> ::Hash[String, String]
@@ -0,0 +1,48 @@
1
+ module OpenAI
2
+ module Helpers
3
+ module Chat
4
+ class ToolRunner
5
+ type handler = ^(Hash[String, untyped]) -> untyped
6
+
7
+ class Error < StandardError
8
+ end
9
+
10
+ class MaxRoundsError < Error
11
+ end
12
+
13
+ # @api private
14
+ def initialize: (
15
+ completions: OpenAI::Resources::Chat::Completions,
16
+ params: Hash[Symbol, untyped],
17
+ tool_handlers: Hash[String, handler],
18
+ max_rounds: Integer
19
+ ) -> void
20
+
21
+ # @api private
22
+ def run: -> OpenAI::Chat::ChatCompletion
23
+ end
24
+ end
25
+ end
26
+
27
+ module Resources
28
+ class Chat
29
+ class Completions
30
+ # @api private
31
+ def create_for_tool_runner: (
32
+ Hash[Symbol, untyped] params
33
+ ) -> OpenAI::Chat::ChatCompletion
34
+
35
+ def run_tools: (
36
+ model: String | Symbol,
37
+ messages: Array[untyped],
38
+ tools: Array[Class
39
+ | OpenAI::Chat::ChatCompletionFunctionTool
40
+ | Hash[Symbol, untyped]],
41
+ tool_handlers: Hash[String, OpenAI::Helpers::Chat::ToolRunner::handler],
42
+ ?max_rounds: Integer,
43
+ **untyped
44
+ ) -> OpenAI::Chat::ChatCompletion
45
+ end
46
+ end
47
+ end
48
+ end
@@ -31,8 +31,6 @@ module OpenAI
31
31
  | ::Hash[Symbol | String, untyped]
32
32
 
33
33
  class UnknownTranslationServerEvent < OpenAI::Realtime::UnknownServerEvent
34
- def inspect: -> String
35
- alias to_s inspect
36
34
  end
37
35
  class TranslationConnection
38
36
  include Enumerable[OpenAI::Models::Realtime::translation_connection_server_event]
@@ -8,6 +8,8 @@ module OpenAI
8
8
  # @api private
9
9
  def initialize: (data: ::Hash[Symbol, untyped]) -> void
10
10
  def to_h: -> ::Hash[Symbol, untyped]
11
+ def inspect: -> String
12
+ alias to_s inspect
11
13
  end
12
14
  end
13
15
  end
@@ -23,17 +23,34 @@ module OpenAI
23
23
  ?transport: untyped,
24
24
  ?transport_options: Hash[untyped, untyped]
25
25
  ) {
26
- (TypedConnection) -> untyped
26
+ (TypedConnection[untyped, untyped]) -> untyped
27
27
  } -> untyped
28
28
  end
29
29
 
30
- class TypedConnection
31
- include Enumerable[untyped]
30
+ module TypedResource[WebSocketClientEvent, WebSocketServerEvent]
31
+ include Resource
32
+
33
+ def connect: (
34
+ *untyped path_arguments,
35
+ ?query: Hash[untyped, untyped],
36
+ ?websocket_base_url: String?,
37
+ ?request_options: untyped,
38
+ ?transport: untyped,
39
+ ?transport_options: Hash[untyped, untyped]
40
+ ) {
41
+ (TypedConnection[WebSocketClientEvent, WebSocketServerEvent]) -> untyped
42
+ } -> untyped
43
+ end
44
+
45
+ class TypedConnection[in ClientEvent, out Elem]
46
+ include Enumerable[Elem]
32
47
 
33
48
  attr_reader url: URI::Generic
34
- def receive: -> untyped
35
- def send_event: (untyped event) -> void
36
- def each: -> Enumerator[untyped, self] | { (untyped) -> void } -> self
49
+ def receive: -> Elem?
50
+ def send_event: (
51
+ ClientEvent | Hash[String | Symbol, untyped] event
52
+ ) -> void
53
+ def each: -> Enumerator[Elem, self] | { (Elem) -> void } -> self
37
54
  def close: (?code: Integer, ?reason: String) -> void
38
55
  def closed?: -> bool
39
56
  end