openai 0.107.0 → 0.109.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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/README.md +55 -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/client_runtime.rb +11 -0
  8. data/lib/openai/helpers/realtime/recovery.rb +8 -2
  9. data/lib/openai/helpers/responses_websocket/incremental.rb +5 -1
  10. data/lib/openai/helpers/responses_websocket/session.rb +11 -4
  11. data/lib/openai/helpers/streaming/chat_completion_resource.rb +52 -0
  12. data/lib/openai/internal/provider.rb +1 -0
  13. data/lib/openai/models/admin/organization/usage_audio_speeches_response.rb +4 -4
  14. data/lib/openai/models/admin/organization/usage_audio_transcriptions_response.rb +4 -4
  15. data/lib/openai/models/admin/organization/usage_code_interpreter_sessions_response.rb +4 -4
  16. data/lib/openai/models/admin/organization/usage_completions_response.rb +4 -4
  17. data/lib/openai/models/admin/organization/usage_costs_response.rb +4 -4
  18. data/lib/openai/models/admin/organization/usage_decisions_response.rb +4 -4
  19. data/lib/openai/models/admin/organization/usage_embeddings_response.rb +4 -4
  20. data/lib/openai/models/admin/organization/usage_file_search_calls_response.rb +4 -4
  21. data/lib/openai/models/admin/organization/usage_images_response.rb +4 -4
  22. data/lib/openai/models/admin/organization/usage_moderations_response.rb +4 -4
  23. data/lib/openai/models/admin/organization/usage_vector_stores_response.rb +4 -4
  24. data/lib/openai/models/admin/organization/usage_web_search_calls_response.rb +4 -4
  25. data/lib/openai/models/audio/voice_consent.rb +58 -0
  26. data/lib/openai/models/audio/voice_consent_create_params.rb +57 -0
  27. data/lib/openai/models/audio/voice_consent_delete_params.rb +22 -0
  28. data/lib/openai/models/audio/voice_consent_deleted.rb +34 -0
  29. data/lib/openai/models/audio/voice_consent_list_params.rb +42 -0
  30. data/lib/openai/models/audio/voice_consent_retrieve_params.rb +22 -0
  31. data/lib/openai/models/audio/voice_consent_update_params.rb +32 -0
  32. data/lib/openai/providers/vertex.rb +229 -0
  33. data/lib/openai/resources/audio/voice_consents.rb +163 -0
  34. data/lib/openai/resources/audio.rb +5 -0
  35. data/lib/openai/version.rb +1 -1
  36. data/lib/openai.rb +9 -0
  37. data/rbi/openai/helpers/chat/tool_runner.rbi +74 -0
  38. data/rbi/openai/internal/provider.rbi +3 -0
  39. data/rbi/openai/models/admin/organization/usage_audio_speeches_response.rbi +4 -4
  40. data/rbi/openai/models/admin/organization/usage_audio_transcriptions_response.rbi +4 -4
  41. data/rbi/openai/models/admin/organization/usage_code_interpreter_sessions_response.rbi +4 -4
  42. data/rbi/openai/models/admin/organization/usage_completions_response.rbi +4 -4
  43. data/rbi/openai/models/admin/organization/usage_costs_response.rbi +4 -4
  44. data/rbi/openai/models/admin/organization/usage_decisions_response.rbi +4 -4
  45. data/rbi/openai/models/admin/organization/usage_embeddings_response.rbi +4 -4
  46. data/rbi/openai/models/admin/organization/usage_file_search_calls_response.rbi +4 -4
  47. data/rbi/openai/models/admin/organization/usage_images_response.rbi +4 -4
  48. data/rbi/openai/models/admin/organization/usage_moderations_response.rbi +4 -4
  49. data/rbi/openai/models/admin/organization/usage_vector_stores_response.rbi +4 -4
  50. data/rbi/openai/models/admin/organization/usage_web_search_calls_response.rbi +4 -4
  51. data/rbi/openai/models/audio/voice_consent.rbi +86 -0
  52. data/rbi/openai/models/audio/voice_consent_create_params.rbi +92 -0
  53. data/rbi/openai/models/audio/voice_consent_delete_params.rbi +53 -0
  54. data/rbi/openai/models/audio/voice_consent_deleted.rbi +62 -0
  55. data/rbi/openai/models/audio/voice_consent_list_params.rbi +78 -0
  56. data/rbi/openai/models/audio/voice_consent_retrieve_params.rbi +53 -0
  57. data/rbi/openai/models/audio/voice_consent_update_params.rbi +62 -0
  58. data/rbi/openai/models/response_format_json_schema.rbi +13 -11
  59. data/rbi/openai/providers.rbi +13 -0
  60. data/rbi/openai/resources/audio/voice_consents.rbi +108 -0
  61. data/rbi/openai/resources/audio.rbi +4 -0
  62. data/sig/openai/helpers/chat/tool_runner.rbs +48 -0
  63. data/sig/openai/internal/provider.rbs +3 -1
  64. data/sig/openai/models/admin/organization/usage_audio_speeches_response.rbs +6 -6
  65. data/sig/openai/models/admin/organization/usage_audio_transcriptions_response.rbs +6 -6
  66. data/sig/openai/models/admin/organization/usage_code_interpreter_sessions_response.rbs +6 -6
  67. data/sig/openai/models/admin/organization/usage_completions_response.rbs +6 -6
  68. data/sig/openai/models/admin/organization/usage_costs_response.rbs +6 -6
  69. data/sig/openai/models/admin/organization/usage_decisions_response.rbs +4 -4
  70. data/sig/openai/models/admin/organization/usage_embeddings_response.rbs +6 -6
  71. data/sig/openai/models/admin/organization/usage_file_search_calls_response.rbs +6 -6
  72. data/sig/openai/models/admin/organization/usage_images_response.rbs +6 -6
  73. data/sig/openai/models/admin/organization/usage_moderations_response.rbs +6 -6
  74. data/sig/openai/models/admin/organization/usage_vector_stores_response.rbs +6 -6
  75. data/sig/openai/models/admin/organization/usage_web_search_calls_response.rbs +6 -6
  76. data/sig/openai/models/audio/voice_consent.rbs +57 -0
  77. data/sig/openai/models/audio/voice_consent_create_params.rbs +61 -0
  78. data/sig/openai/models/audio/voice_consent_delete_params.rbs +25 -0
  79. data/sig/openai/models/audio/voice_consent_deleted.rbs +31 -0
  80. data/sig/openai/models/audio/voice_consent_list_params.rbs +57 -0
  81. data/sig/openai/models/audio/voice_consent_retrieve_params.rbs +25 -0
  82. data/sig/openai/models/audio/voice_consent_update_params.rbs +36 -0
  83. data/sig/openai/providers.rbs +8 -0
  84. data/sig/openai/resources/audio/voice_consents.rbs +38 -0
  85. data/sig/openai/resources/audio.rbs +2 -0
  86. data/vertex.md +29 -0
  87. metadata +32 -1
@@ -0,0 +1,229 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "timeout"
4
+
5
+ module OpenAI
6
+ module Providers
7
+ # @api private
8
+ module Vertex
9
+ SCOPE = "https://www.googleapis.com/auth/cloud-platform"
10
+ AUTH_MARKER = :openai_vertex_bearer
11
+
12
+ class Definition
13
+ def initialize(base_url:, token_provider:, credentials:)
14
+ @base_url = base_url.freeze
15
+ @token_provider = token_provider
16
+ @credentials = credentials
17
+ @credentials_mutex = Mutex.new
18
+ end
19
+
20
+ def name = "vertex"
21
+
22
+ def configure
23
+ token_provider = @token_provider
24
+ credentials = @credentials
25
+ unless token_provider || credentials
26
+ begin
27
+ require "googleauth"
28
+
29
+ rescue LoadError => e
30
+ raise LoadError.new("Vertex ADC requires optional gem \"googleauth\"; add it to your Gemfile."), cause: e
31
+ end
32
+
33
+ begin
34
+ credentials = Google::Auth.get_application_default(SCOPE)
35
+ rescue StandardError => e
36
+ raise OpenAI::Errors::Error.new("Vertex could not load Google Application Default Credentials."), cause: e
37
+ end
38
+ end
39
+
40
+ if credentials
41
+ # googleauth apply! refreshes expired tokens. Serialize just this
42
+ # cache/refresh step across all clients using this provider.
43
+ mutex = @credentials_mutex
44
+ rejected_token = nil
45
+ token_provider = lambda do
46
+ headers = {}
47
+ mutex.synchronize do
48
+ credentials.apply!(headers)
49
+ token = headers.fetch(:authorization) { headers.fetch("authorization") }.delete_prefix("Bearer ")
50
+ if token == rejected_token && credentials.respond_to?(:fetch_access_token!)
51
+ credentials.fetch_access_token!
52
+ credentials.apply!(headers)
53
+ token = headers.fetch(:authorization) { headers.fetch("authorization") }.delete_prefix("Bearer ")
54
+ rejected_token = nil
55
+ end
56
+
57
+ token
58
+ end
59
+ end
60
+ end
61
+
62
+ # Share the replay allowance and retry count, but reset the deadline
63
+ # for each ordinary transport retry. A 401 replay keeps its deadline.
64
+ # Refresh itself happens in prepare_request, under its timeout and mutex.
65
+ if credentials.respond_to?(:fetch_access_token!)
66
+ wrapper = lambda do |request, replayable, retry_count, &send_request|
67
+ context = request[:vertex_auth_context] || {replayed: false}
68
+ context[:retry_count] = retry_count
69
+ context[:deadline] = request[:timeout]&.then { OpenAI::Internal::Util.monotonic_secs + _1 }
70
+ request = request.merge(vertex_auth_context: context)
71
+ begin
72
+ send_request.call(request, context[:retry_count])
73
+ rescue OpenAI::Errors::AuthenticationError
74
+ remaining = context[:deadline] && (context[:deadline] - OpenAI::Internal::Util.monotonic_secs)
75
+ if remaining && remaining <= 0
76
+ raise OpenAI::Errors::APITimeoutError.new(url: request.fetch(:url))
77
+ end
78
+
79
+ begin
80
+ Timeout.timeout(remaining) { mutex.synchronize { rejected_token = context[:token] } }
81
+ rescue Timeout::Error
82
+ raise OpenAI::Errors::APITimeoutError.new(url: request.fetch(:url)), cause: nil
83
+ end
84
+
85
+ raise if context[:replayed] || !replayable || context[:retry_count] >= request.fetch(:max_retries)
86
+
87
+ context[:replayed] = true
88
+ context[:retry_count] += 1
89
+ retry
90
+ end
91
+ end
92
+ end
93
+
94
+ base = URI(@base_url)
95
+ OpenAI::Internal::Provider::Runtime.new(
96
+ name: name,
97
+ base_url: @base_url,
98
+ authentication_headers: %w[authorization],
99
+ wrap_request: wrapper,
100
+ prepare_request: lambda do |request|
101
+ url = request.fetch(:url)
102
+ unless OpenAI::Internal::Util.uri_origin(url) == OpenAI::Internal::Util.uri_origin(base)
103
+ raise OpenAI::Errors::Error, "Vertex refuses credentials for an origin other than the configured URL."
104
+ end
105
+
106
+ headers = request.fetch(:headers).dup
107
+ if request[:provider_auth] == AUTH_MARKER
108
+ headers.delete("authorization")
109
+ elsif headers.key?("authorization")
110
+ raise(
111
+ OpenAI::Errors::Error,
112
+ "Vertex authentication cannot be combined with a custom Authorization header."
113
+ )
114
+ end
115
+
116
+ if headers.key?("api-key")
117
+ raise OpenAI::Errors::Error, "Vertex authentication cannot be combined with a custom api-key header."
118
+ end
119
+ # The outer Google API version differs for stored Responses.
120
+ # Do not change other gateway layouts.
121
+ prefix = "#{base.path.delete_suffix("/")}/responses/"
122
+ if [:get, :delete].include?(request[:method]) &&
123
+ url.path.start_with?(prefix) &&
124
+ base.path.start_with?("/v1/projects/")
125
+ url = url.dup
126
+ url.path = url.path.sub(%r{\A/v1/}, "/v1beta1/")
127
+ end
128
+
129
+ headers.delete("openai-organization")
130
+ headers.delete("openai-project")
131
+ timeout = request[:timeout]
132
+ context = request[:vertex_auth_context]
133
+ timeout = context[:deadline] - OpenAI::Internal::Util.monotonic_secs if context&.dig(:deadline)
134
+ if timeout && timeout <= 0
135
+ raise OpenAI::Errors::APITimeoutError.new(url: url, message: "Vertex credential lookup timed out")
136
+ end
137
+
138
+ started = OpenAI::Internal::Util.monotonic_secs
139
+ token = begin
140
+ Timeout.timeout(timeout) { token_provider.call }
141
+ rescue Timeout::Error => e
142
+ raise(
143
+ OpenAI::Errors::APITimeoutError.new(url: url, message: "Vertex credential lookup timed out"),
144
+ cause: e
145
+ )
146
+ rescue StandardError => e
147
+ raise OpenAI::Errors::Error.new("Vertex failed to resolve Google credentials."), cause: e
148
+ end
149
+
150
+ remaining = timeout && (timeout - (OpenAI::Internal::Util.monotonic_secs - started))
151
+ if remaining && remaining <= 0
152
+ raise OpenAI::Errors::APITimeoutError.new(url: url, message: "Vertex credential lookup timed out")
153
+ end
154
+
155
+ if credentials.respond_to?(:quota_project_id) && (quota = credentials.quota_project_id)
156
+ headers["x-goog-user-project"] = quota
157
+ end
158
+
159
+ unless token.is_a?(String) && !token.strip.empty?
160
+ raise OpenAI::Errors::Error, "Vertex token_provider must return a non-empty access token string."
161
+ end
162
+
163
+ context[:token] = token if context
164
+
165
+ request.merge(
166
+ url: url,
167
+ timeout: remaining,
168
+ headers: headers.merge("authorization" => "Bearer #{token}"),
169
+ provider_auth: AUTH_MARKER,
170
+ follow_redirects: false
171
+ )
172
+ end
173
+ )
174
+ end
175
+ end
176
+ end
177
+
178
+ class << self
179
+ # Use Google Application Default Credentials with the regular Responses
180
+ # client. Supply token_provider: -> { ... } for application-managed credentials.
181
+ # It is called per attempt and should cache/refresh tokens as needed.
182
+ #
183
+ # Base URL is the complete trusted provider URL before /responses. When
184
+ # omitted, project and location are required. OpenAI environment defaults
185
+ # and top-level auth/base_url options are ignored/rejected by Client.
186
+ def vertex(project: nil, location: nil, base_url: nil, token_provider: nil, credentials: nil)
187
+ if credentials && token_provider
188
+ raise ArgumentError, "Vertex credentials and token_provider are mutually exclusive."
189
+ end
190
+
191
+ if credentials && !credentials.respond_to?(:apply!)
192
+ raise ArgumentError, "Vertex credentials must provide Google's apply! method."
193
+ end
194
+
195
+ unless token_provider.nil? || token_provider.respond_to?(:call)
196
+ raise ArgumentError, "Vertex token_provider must respond to call."
197
+ end
198
+
199
+ if base_url.nil?
200
+ project_segment = /\A[a-zA-Z0-9][a-zA-Z0-9_.:-]*\z/
201
+ location_segment = /\A[a-zA-Z0-9][a-zA-Z0-9_-]*\z/
202
+ unless project.is_a?(String) &&
203
+ location.is_a?(String) &&
204
+ project_segment.match?(project) &&
205
+ location_segment.match?(location)
206
+ raise ArgumentError, "Vertex project and location are required and must be single path segments."
207
+ end
208
+
209
+ host = location == "global" ? "aiplatform.googleapis.com" : "#{location}-aiplatform.googleapis.com"
210
+ base_url = "https://#{host}/v1/projects/#{project}/locations/#{location}/publishers/openai/v1"
211
+ end
212
+
213
+ begin
214
+ uri = URI(base_url.to_s)
215
+ unless %w[http https].include?(uri.scheme) && uri.host && !uri.userinfo && !uri.query && !uri.fragment
216
+ raise URI::InvalidURIError
217
+ end
218
+
219
+ rescue URI::InvalidURIError
220
+ raise ArgumentError, "Vertex base_url must be an absolute HTTP(S) URL without credentials, query or fragment."
221
+ end
222
+
223
+ OpenAI::Internal::Provider.create(
224
+ Vertex::Definition.new(base_url: uri.to_s, token_provider: token_provider, credentials: credentials)
225
+ )
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenAI
4
+ module Resources
5
+ class Audio
6
+ # Turn audio into text or text into audio.
7
+ class VoiceConsents
8
+ # Upload a voice consent recording.
9
+ #
10
+ # `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
11
+ # metadata. Use `OpenAI::FilePart` when you need to override the filename or
12
+ # content type.
13
+ #
14
+ # @overload create(language:, name:, recording:, request_options: {})
15
+ #
16
+ # @param language [String]
17
+ # The BCP 47 language tag for the consent phrase (for example, `en-US`).
18
+ #
19
+ # @param name [String]
20
+ # The label to use for this consent recording.
21
+ #
22
+ # @param recording [Pathname, StringIO, IO, String, OpenAI::FilePart]
23
+ # The consent audio recording file. Maximum size is 10 MiB.
24
+ #
25
+ # Supported MIME types: `audio/mpeg`, `audio/wav`, `audio/x-wav`, `audio/ogg`,
26
+ # `audio/aac`, `audio/flac`, `audio/webm`, `audio/mp4`.
27
+ #
28
+ # `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
29
+ # metadata. Use `OpenAI::FilePart` when you need to override the filename or
30
+ # content type.
31
+ #
32
+ # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil]
33
+ #
34
+ # @return [OpenAI::Models::Audio::VoiceConsent]
35
+ #
36
+ # @see OpenAI::Models::Audio::VoiceConsentCreateParams
37
+ def create(params)
38
+ parsed, options = OpenAI::Audio::VoiceConsentCreateParams.dump_request(params)
39
+ @client.request(
40
+ method: :post,
41
+ path: "audio/voice_consents",
42
+ headers: {"content-type" => "multipart/form-data"},
43
+ body: parsed,
44
+ model: OpenAI::Audio::VoiceConsent,
45
+ security: {bearer_auth: true},
46
+ options: options
47
+ )
48
+ end
49
+
50
+ # Retrieves a voice consent recording.
51
+ #
52
+ # @overload retrieve(consent_id, request_options: {})
53
+ #
54
+ # @param consent_id [String]
55
+ # The ID of the consent recording to retrieve.
56
+ #
57
+ # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil]
58
+ #
59
+ # @return [OpenAI::Models::Audio::VoiceConsent]
60
+ #
61
+ # @see OpenAI::Models::Audio::VoiceConsentRetrieveParams
62
+ def retrieve(consent_id, params = {})
63
+ @client.request(
64
+ method: :get,
65
+ path: ["audio/voice_consents/%1$s", consent_id],
66
+ model: OpenAI::Audio::VoiceConsent,
67
+ security: {bearer_auth: true},
68
+ options: params[:request_options]
69
+ )
70
+ end
71
+
72
+ # Updates a voice consent recording (metadata only).
73
+ #
74
+ # @overload update(consent_id, name:, request_options: {})
75
+ #
76
+ # @param consent_id [String]
77
+ # The ID of the consent recording to update.
78
+ #
79
+ # @param name [String]
80
+ # The updated label for this consent recording.
81
+ #
82
+ # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil]
83
+ #
84
+ # @return [OpenAI::Models::Audio::VoiceConsent]
85
+ #
86
+ # @see OpenAI::Models::Audio::VoiceConsentUpdateParams
87
+ def update(consent_id, params)
88
+ parsed, options = OpenAI::Audio::VoiceConsentUpdateParams.dump_request(params)
89
+ @client.request(
90
+ method: :post,
91
+ path: ["audio/voice_consents/%1$s", consent_id],
92
+ body: parsed,
93
+ model: OpenAI::Audio::VoiceConsent,
94
+ security: {bearer_auth: true},
95
+ options: options
96
+ )
97
+ end
98
+
99
+ # Returns a list of voice consent recordings.
100
+ #
101
+ # @overload list(after: nil, limit: nil, request_options: {})
102
+ #
103
+ # @param after [String]
104
+ # A cursor for use in pagination. `after` is an object ID that defines your place
105
+ # in the list. For instance, if you make a list request and receive 100 objects,
106
+ # ending with obj_foo, your subsequent call can include after=obj_foo in order to
107
+ # fetch the next page of the list.
108
+ #
109
+ # @param limit [Integer]
110
+ # A limit on the number of objects to be returned. Limit can range between 1 and
111
+ # 100, and the default is 20.
112
+ #
113
+ # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil]
114
+ #
115
+ # @return [OpenAI::Internal::CursorPage<OpenAI::Models::Audio::VoiceConsent>]
116
+ #
117
+ # @see OpenAI::Models::Audio::VoiceConsentListParams
118
+ def list(params = {})
119
+ parsed, options = OpenAI::Audio::VoiceConsentListParams.dump_request(params)
120
+ query = OpenAI::Internal::Util.encode_query_params(parsed)
121
+ @client.request(
122
+ method: :get,
123
+ path: "audio/voice_consents",
124
+ query: query,
125
+ page: OpenAI::Internal::CursorPage,
126
+ model: OpenAI::Audio::VoiceConsent,
127
+ security: {bearer_auth: true},
128
+ options: options
129
+ )
130
+ end
131
+
132
+ # Deletes a voice consent recording.
133
+ #
134
+ # @overload delete(consent_id, request_options: {})
135
+ #
136
+ # @param consent_id [String]
137
+ # The ID of the consent recording to delete.
138
+ #
139
+ # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil]
140
+ #
141
+ # @return [OpenAI::Models::Audio::VoiceConsentDeleted]
142
+ #
143
+ # @see OpenAI::Models::Audio::VoiceConsentDeleteParams
144
+ def delete(consent_id, params = {})
145
+ @client.request(
146
+ method: :delete,
147
+ path: ["audio/voice_consents/%1$s", consent_id],
148
+ model: OpenAI::Audio::VoiceConsentDeleted,
149
+ security: {bearer_auth: true},
150
+ options: params[:request_options]
151
+ )
152
+ end
153
+
154
+ # @api private
155
+ #
156
+ # @param client [OpenAI::Client]
157
+ def initialize(client:)
158
+ @client = client
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
@@ -19,6 +19,10 @@ module OpenAI
19
19
  # @return [OpenAI::Resources::Audio::Voices]
20
20
  attr_reader :voices
21
21
 
22
+ # Turn audio into text or text into audio.
23
+ # @return [OpenAI::Resources::Audio::VoiceConsents]
24
+ attr_reader :voice_consents
25
+
22
26
  # @api private
23
27
  #
24
28
  # @param client [OpenAI::Client]
@@ -28,6 +32,7 @@ module OpenAI
28
32
  @translations = OpenAI::Resources::Audio::Translations.new(client: client)
29
33
  @speech = OpenAI::Resources::Audio::Speech.new(client: client)
30
34
  @voices = OpenAI::Resources::Audio::Voices.new(client: client)
35
+ @voice_consents = OpenAI::Resources::Audio::VoiceConsents.new(client: client)
31
36
  end
32
37
  end
33
38
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenAI
4
- VERSION = "0.107.0"
4
+ VERSION = "0.109.0"
5
5
  end
data/lib/openai.rb CHANGED
@@ -69,6 +69,7 @@ require_relative "openai/provider"
69
69
  require_relative "openai/internal/provider"
70
70
  require_relative "openai/providers/azure"
71
71
  require_relative "openai/providers/bedrock"
72
+ require_relative "openai/providers/vertex"
72
73
  require_relative "openai/internal/transport/request_body_merge"
73
74
  require_relative "openai/internal/transport/base_client"
74
75
  require_relative "openai/helpers/client_options"
@@ -462,6 +463,13 @@ require_relative "openai/models/audio/translation_create_params"
462
463
  require_relative "openai/models/audio/translation_create_response"
463
464
  require_relative "openai/models/audio/translation_verbose"
464
465
  require_relative "openai/models/audio/voice"
466
+ require_relative "openai/models/audio/voice_consent"
467
+ require_relative "openai/models/audio/voice_consent_create_params"
468
+ require_relative "openai/models/audio/voice_consent_deleted"
469
+ require_relative "openai/models/audio/voice_consent_delete_params"
470
+ require_relative "openai/models/audio/voice_consent_list_params"
471
+ require_relative "openai/models/audio/voice_consent_retrieve_params"
472
+ require_relative "openai/models/audio/voice_consent_update_params"
465
473
  require_relative "openai/models/audio/voice_create_params"
466
474
  require_relative "openai/models/audio_model"
467
475
  require_relative "openai/models/audio_response_format"
@@ -1558,6 +1566,7 @@ require_relative "openai/resources/audio"
1558
1566
  require_relative "openai/resources/audio/speech"
1559
1567
  require_relative "openai/resources/audio/transcriptions"
1560
1568
  require_relative "openai/resources/audio/translations"
1569
+ require_relative "openai/resources/audio/voice_consents"
1561
1570
  require_relative "openai/resources/audio/voices"
1562
1571
  require_relative "openai/resources/batches"
1563
1572
  require_relative "openai/resources/beta"
@@ -0,0 +1,74 @@
1
+ # typed: strong
2
+
3
+ module OpenAI
4
+ module Helpers
5
+ module Chat
6
+ class ToolRunner
7
+ Handler = T.type_alias { T.proc.params(arguments: T::Hash[String, T.untyped]).returns(T.untyped) }
8
+
9
+ class Error < StandardError
10
+ end
11
+
12
+ class MaxRoundsError < Error
13
+ end
14
+
15
+ # @api private
16
+ sig do
17
+ params(
18
+ completions: OpenAI::Resources::Chat::Completions,
19
+ params: T::Hash[Symbol, T.untyped],
20
+ tool_handlers: T::Hash[String, Handler],
21
+ max_rounds: Integer
22
+ )
23
+ .void
24
+ end
25
+ def initialize(completions:, params:, tool_handlers:, max_rounds:)
26
+ end
27
+
28
+ # @api private
29
+ sig { returns(OpenAI::Chat::ChatCompletion) }
30
+ def run
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ module Resources
37
+ class Chat
38
+ class Completions
39
+ # @api private
40
+ sig { params(params: T::Hash[Symbol, T.untyped]).returns(OpenAI::Chat::ChatCompletion) }
41
+ def create_for_tool_runner(params)
42
+ end
43
+
44
+ sig do
45
+ params(
46
+ model: T.any(String, OpenAI::ChatModel::OrSymbol),
47
+ messages: T::Array[
48
+ T.any(
49
+ OpenAI::Chat::ChatCompletionDeveloperMessageParam::OrHash,
50
+ OpenAI::Chat::ChatCompletionSystemMessageParam::OrHash,
51
+ OpenAI::Chat::ChatCompletionUserMessageParam::OrHash,
52
+ OpenAI::Chat::ChatCompletionAssistantMessageParam::OrHash,
53
+ OpenAI::Chat::ChatCompletionToolMessageParam::OrHash,
54
+ OpenAI::Chat::ChatCompletionFunctionMessageParam::OrHash
55
+ )
56
+ ],
57
+ tools: T::Array[
58
+ T.any(
59
+ OpenAI::StructuredOutput::JsonSchemaConverter,
60
+ OpenAI::Chat::ChatCompletionFunctionTool::OrHash
61
+ )
62
+ ],
63
+ tool_handlers: T::Hash[String, OpenAI::Helpers::Chat::ToolRunner::Handler],
64
+ max_rounds: Integer,
65
+ params: T.untyped
66
+ )
67
+ .returns(OpenAI::Chat::ChatCompletion)
68
+ end
69
+ def run_tools(model:, messages:, tools:, tool_handlers:, max_rounds: 10, **params)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -25,6 +25,9 @@ module OpenAI
25
25
 
26
26
  attr_accessor :prepare_request
27
27
 
28
+ sig { returns(T.nilable(Proc)) }
29
+ attr_accessor :wrap_request
30
+
28
31
  sig { returns(T::Array[String]) }
29
32
  attr_accessor :authentication_headers
30
33
  end
@@ -232,8 +232,8 @@ module OpenAI
232
232
  sig { returns(T.nilable(Integer)) }
233
233
  attr_accessor :input_cache_write_30m_tokens
234
234
 
235
- # The aggregated number of input tokens written to the cache with a 30-minute
236
- # retention period.
235
+ # The aggregated number of input tokens written to the cache across 30-minute and
236
+ # 12-hour retention periods.
237
237
  sig { returns(T.nilable(Integer)) }
238
238
  attr_reader :input_cache_write_tokens
239
239
 
@@ -431,8 +431,8 @@ module OpenAI
431
431
  # retention period. May be absent or null for older responses.
432
432
  input_cache_write_30m_tokens: nil,
433
433
 
434
- # The aggregated number of input tokens written to the cache with a 30-minute
435
- # retention period.
434
+ # The aggregated number of input tokens written to the cache across 30-minute and
435
+ # 12-hour retention periods.
436
436
  input_cache_write_tokens: nil,
437
437
 
438
438
  # The aggregated number of cached audio input tokens used.
@@ -234,8 +234,8 @@ module OpenAI
234
234
  sig { returns(T.nilable(Integer)) }
235
235
  attr_accessor :input_cache_write_30m_tokens
236
236
 
237
- # The aggregated number of input tokens written to the cache with a 30-minute
238
- # retention period.
237
+ # The aggregated number of input tokens written to the cache across 30-minute and
238
+ # 12-hour retention periods.
239
239
  sig { returns(T.nilable(Integer)) }
240
240
  attr_reader :input_cache_write_tokens
241
241
 
@@ -433,8 +433,8 @@ module OpenAI
433
433
  # retention period. May be absent or null for older responses.
434
434
  input_cache_write_30m_tokens: nil,
435
435
 
436
- # The aggregated number of input tokens written to the cache with a 30-minute
437
- # retention period.
436
+ # The aggregated number of input tokens written to the cache across 30-minute and
437
+ # 12-hour retention periods.
438
438
  input_cache_write_tokens: nil,
439
439
 
440
440
  # The aggregated number of cached audio input tokens used.
@@ -236,8 +236,8 @@ module OpenAI
236
236
  sig { returns(T.nilable(Integer)) }
237
237
  attr_accessor :input_cache_write_30m_tokens
238
238
 
239
- # The aggregated number of input tokens written to the cache with a 30-minute
240
- # retention period.
239
+ # The aggregated number of input tokens written to the cache across 30-minute and
240
+ # 12-hour retention periods.
241
241
  sig { returns(T.nilable(Integer)) }
242
242
  attr_reader :input_cache_write_tokens
243
243
 
@@ -435,8 +435,8 @@ module OpenAI
435
435
  # retention period. May be absent or null for older responses.
436
436
  input_cache_write_30m_tokens: nil,
437
437
 
438
- # The aggregated number of input tokens written to the cache with a 30-minute
439
- # retention period.
438
+ # The aggregated number of input tokens written to the cache across 30-minute and
439
+ # 12-hour retention periods.
440
440
  input_cache_write_tokens: nil,
441
441
 
442
442
  # The aggregated number of cached audio input tokens used.
@@ -232,8 +232,8 @@ module OpenAI
232
232
  sig { returns(T.nilable(Integer)) }
233
233
  attr_accessor :input_cache_write_30m_tokens
234
234
 
235
- # The aggregated number of input tokens written to the cache with a 30-minute
236
- # retention period.
235
+ # The aggregated number of input tokens written to the cache across 30-minute and
236
+ # 12-hour retention periods.
237
237
  sig { returns(T.nilable(Integer)) }
238
238
  attr_reader :input_cache_write_tokens
239
239
 
@@ -431,8 +431,8 @@ module OpenAI
431
431
  # retention period. May be absent or null for older responses.
432
432
  input_cache_write_30m_tokens: nil,
433
433
 
434
- # The aggregated number of input tokens written to the cache with a 30-minute
435
- # retention period.
434
+ # The aggregated number of input tokens written to the cache across 30-minute and
435
+ # 12-hour retention periods.
436
436
  input_cache_write_tokens: nil,
437
437
 
438
438
  # The aggregated number of cached audio input tokens used.
@@ -228,8 +228,8 @@ module OpenAI
228
228
  sig { returns(T.nilable(Integer)) }
229
229
  attr_accessor :input_cache_write_30m_tokens
230
230
 
231
- # The aggregated number of input tokens written to the cache with a 30-minute
232
- # retention period.
231
+ # The aggregated number of input tokens written to the cache across 30-minute and
232
+ # 12-hour retention periods.
233
233
  sig { returns(T.nilable(Integer)) }
234
234
  attr_reader :input_cache_write_tokens
235
235
 
@@ -427,8 +427,8 @@ module OpenAI
427
427
  # retention period. May be absent or null for older responses.
428
428
  input_cache_write_30m_tokens: nil,
429
429
 
430
- # The aggregated number of input tokens written to the cache with a 30-minute
431
- # retention period.
430
+ # The aggregated number of input tokens written to the cache across 30-minute and
431
+ # 12-hour retention periods.
432
432
  input_cache_write_tokens: nil,
433
433
 
434
434
  # The aggregated number of cached audio input tokens used.
@@ -188,8 +188,8 @@ module OpenAI
188
188
  sig { returns(T.nilable(Integer)) }
189
189
  attr_accessor :input_cache_write_30m_tokens
190
190
 
191
- # The aggregated number of input tokens written to the cache with a 30-minute
192
- # retention period.
191
+ # The aggregated number of input tokens written to the cache across 30-minute and
192
+ # 12-hour retention periods.
193
193
  sig { returns(T.nilable(Integer)) }
194
194
  attr_accessor :input_cache_write_tokens
195
195
 
@@ -354,8 +354,8 @@ module OpenAI
354
354
  # retention period.
355
355
  input_cache_write_30m_tokens: nil,
356
356
 
357
- # The aggregated number of input tokens written to the cache with a 30-minute
358
- # retention period.
357
+ # The aggregated number of input tokens written to the cache across 30-minute and
358
+ # 12-hour retention periods.
359
359
  input_cache_write_tokens: nil,
360
360
 
361
361
  # The aggregated number of cached audio input tokens used.