openai 0.70.0 → 0.71.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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/README.md +51 -1
  4. data/lib/openai/client.rb +62 -8
  5. data/lib/openai/internal/provider.rb +31 -0
  6. data/lib/openai/internal/transport/base_client.rb +65 -21
  7. data/lib/openai/models/admin/organization/audit_log_list_params.rb +84 -0
  8. data/lib/openai/models/admin/organization/audit_log_list_response.rb +84 -0
  9. data/lib/openai/models/admin/organization/projects/project_service_account.rb +4 -3
  10. data/lib/openai/models/admin/organization/projects/service_account_create_params.rb +9 -1
  11. data/lib/openai/models/admin/organization/projects/service_account_create_response.rb +26 -6
  12. data/lib/openai/models/admin/organization/projects/service_accounts/api_key_create_params.rb +54 -0
  13. data/lib/openai/models/admin/organization/projects/service_accounts/api_key_create_response.rb +57 -0
  14. data/lib/openai/models/admin/organization/usage_audio_speeches_response.rb +88 -13
  15. data/lib/openai/models/admin/organization/usage_audio_transcriptions_response.rb +88 -13
  16. data/lib/openai/models/admin/organization/usage_code_interpreter_sessions_response.rb +88 -13
  17. data/lib/openai/models/admin/organization/usage_completions_response.rb +88 -13
  18. data/lib/openai/models/admin/organization/usage_costs_response.rb +88 -13
  19. data/lib/openai/models/admin/organization/usage_embeddings_response.rb +88 -13
  20. data/lib/openai/models/admin/organization/usage_file_search_calls_response.rb +88 -13
  21. data/lib/openai/models/admin/organization/usage_images_response.rb +88 -13
  22. data/lib/openai/models/admin/organization/usage_moderations_response.rb +88 -13
  23. data/lib/openai/models/admin/organization/usage_vector_stores_response.rb +88 -13
  24. data/lib/openai/models/admin/organization/usage_web_search_calls_response.rb +88 -13
  25. data/lib/openai/models/beta/beta_response_input_item.rb +16 -32
  26. data/lib/openai/provider.rb +18 -0
  27. data/lib/openai/providers/bedrock.rb +489 -0
  28. data/lib/openai/resources/admin/organization/projects/service_accounts/api_keys.rb +60 -0
  29. data/lib/openai/resources/admin/organization/projects/service_accounts.rb +10 -3
  30. data/lib/openai/version.rb +1 -1
  31. data/lib/openai.rb +6 -0
  32. data/rbi/openai/client.rbi +17 -0
  33. data/rbi/openai/internal/provider.rbi +51 -0
  34. data/rbi/openai/internal/transport/base_client.rbi +32 -0
  35. data/rbi/openai/models/admin/organization/audit_log_list_params.rbi +420 -0
  36. data/rbi/openai/models/admin/organization/audit_log_list_response.rbi +420 -0
  37. data/rbi/openai/models/admin/organization/projects/project_service_account.rbi +8 -3
  38. data/rbi/openai/models/admin/organization/projects/service_account_create_params.rbi +8 -0
  39. data/rbi/openai/models/admin/organization/projects/service_account_create_response.rbi +52 -8
  40. data/rbi/openai/models/admin/organization/projects/service_accounts/api_key_create_params.rbi +84 -0
  41. data/rbi/openai/models/admin/organization/projects/service_accounts/api_key_create_response.rbi +80 -0
  42. data/rbi/openai/models/admin/organization/usage_audio_speeches_response.rbi +121 -16
  43. data/rbi/openai/models/admin/organization/usage_audio_transcriptions_response.rbi +121 -16
  44. data/rbi/openai/models/admin/organization/usage_code_interpreter_sessions_response.rbi +121 -16
  45. data/rbi/openai/models/admin/organization/usage_completions_response.rbi +121 -16
  46. data/rbi/openai/models/admin/organization/usage_costs_response.rbi +121 -16
  47. data/rbi/openai/models/admin/organization/usage_embeddings_response.rbi +121 -16
  48. data/rbi/openai/models/admin/organization/usage_file_search_calls_response.rbi +121 -16
  49. data/rbi/openai/models/admin/organization/usage_images_response.rbi +121 -16
  50. data/rbi/openai/models/admin/organization/usage_moderations_response.rbi +121 -16
  51. data/rbi/openai/models/admin/organization/usage_vector_stores_response.rbi +121 -16
  52. data/rbi/openai/models/admin/organization/usage_web_search_calls_response.rbi +121 -16
  53. data/rbi/openai/models/beta/beta_response_input_item.rbi +39 -46
  54. data/rbi/openai/provider.rbi +9 -0
  55. data/rbi/openai/providers.rbi +33 -0
  56. data/rbi/openai/resources/admin/organization/projects/service_accounts/api_keys.rbi +45 -0
  57. data/rbi/openai/resources/admin/organization/projects/service_accounts.rbi +12 -2
  58. data/sig/openai/client.rbs +7 -0
  59. data/sig/openai/internal/provider.rbs +29 -0
  60. data/sig/openai/internal/transport/base_client.rbs +17 -1
  61. data/sig/openai/models/admin/organization/audit_log_list_params.rbs +168 -0
  62. data/sig/openai/models/admin/organization/audit_log_list_response.rbs +168 -0
  63. data/sig/openai/models/admin/organization/projects/project_service_account.rbs +2 -1
  64. data/sig/openai/models/admin/organization/projects/service_account_create_params.rbs +9 -1
  65. data/sig/openai/models/admin/organization/projects/service_account_create_response.rbs +16 -5
  66. data/sig/openai/models/admin/organization/projects/service_accounts/api_key_create_params.rbs +53 -0
  67. data/sig/openai/models/admin/organization/projects/service_accounts/api_key_create_response.rbs +48 -0
  68. data/sig/openai/models/admin/organization/usage_audio_speeches_response.rbs +63 -0
  69. data/sig/openai/models/admin/organization/usage_audio_transcriptions_response.rbs +63 -0
  70. data/sig/openai/models/admin/organization/usage_code_interpreter_sessions_response.rbs +63 -0
  71. data/sig/openai/models/admin/organization/usage_completions_response.rbs +63 -0
  72. data/sig/openai/models/admin/organization/usage_costs_response.rbs +63 -0
  73. data/sig/openai/models/admin/organization/usage_embeddings_response.rbs +63 -0
  74. data/sig/openai/models/admin/organization/usage_file_search_calls_response.rbs +63 -0
  75. data/sig/openai/models/admin/organization/usage_images_response.rbs +63 -0
  76. data/sig/openai/models/admin/organization/usage_moderations_response.rbs +63 -0
  77. data/sig/openai/models/admin/organization/usage_vector_stores_response.rbs +63 -0
  78. data/sig/openai/models/admin/organization/usage_web_search_calls_response.rbs +63 -0
  79. data/sig/openai/models/beta/beta_response_input_item.rbs +18 -24
  80. data/sig/openai/provider.rbs +5 -0
  81. data/sig/openai/providers.rbs +15 -0
  82. data/sig/openai/resources/admin/organization/projects/service_accounts/api_keys.rbs +23 -0
  83. data/sig/openai/resources/admin/organization/projects/service_accounts.rbs +3 -0
  84. metadata +20 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46c365e5b18df8765a0afe25ad8068ba9affbec2b802aa6197e462fa4c160f0a
4
- data.tar.gz: '06975c809d77b61a966516da0aca78cd93a313c6854383418608a791d4ed9a9e'
3
+ metadata.gz: d45de13708938c3dc943b2853f9f5117a2dbc8d857c1baeef8495122171a128e
4
+ data.tar.gz: 3606a6326a4ae576e012802835943bd21b1c1806bef44814579b2c2368230417
5
5
  SHA512:
6
- metadata.gz: 8bf4d31c0f5932f9846f3efa54ad1e7e677c5ccb7bb1eeedf6e04f213a094550f4fd1ddf8a053cd4c3850298e9a6be1088187db123dba0d90197c81d7c223c9a
7
- data.tar.gz: a48eb1b00500fae6a6cbeeae07dd309407d385317855c3af5b62ee3dd943f66ff5697bb7de19fb4d8f2eaa96444b368418817688549cb522a3343df4b8816c4d
6
+ metadata.gz: 898be95f8919ba95d82f477624721355a3d8657cc6cdcf240ecc2c48b835322e54f3293559a1402ae9f5e9a3029d731bc58a796ba4432869e4008772ec74439d
7
+ data.tar.gz: b19fcdc7009017b028bcbe99d8e20496f9955509b59507ff3f28917bf7bc89d22fd9aa53f28b0ed07812707dab7ff2622de595efafc547a958ad13dcb24c7df4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.71.0 (2026-07-17)
4
+
5
+ Full Changelog: [v0.70.0...v0.71.0](https://github.com/openai/openai-ruby/compare/v0.70.0...v0.71.0)
6
+
7
+ ### Features
8
+
9
+ * **api:** /organization/projects/{project_id}/service_accounts/{service_account_id}/api_keys" endpoint ([fc60012](https://github.com/openai/openai-ruby/commit/fc6001297f385326c0b9d9c9cbf7f7bd66620c11))
10
+ * **api:** manual updates ([4e499e5](https://github.com/openai/openai-ruby/commit/4e499e5e0ecee6306bde22b2b77cad619395a6cb))
11
+ * **api:** manual updates ([2be1795](https://github.com/openai/openai-ruby/commit/2be179523d2d2838982ce8d6831c49fd324ccf35))
12
+
3
13
  ## 0.70.0 (2026-07-14)
4
14
 
5
15
  Full Changelog: [v0.69.0...v0.70.0](https://github.com/openai/openai-ruby/compare/v0.69.0...v0.70.0)
data/README.md CHANGED
@@ -15,7 +15,7 @@ To use this gem, install via Bundler by adding the following to your application
15
15
  <!-- x-release-please-start-version -->
16
16
 
17
17
  ```ruby
18
- gem "openai", "~> 0.70.0"
18
+ gem "openai", "~> 0.71.0"
19
19
  ```
20
20
 
21
21
  <!-- x-release-please-end -->
@@ -107,6 +107,56 @@ puts(edited.data.first)
107
107
 
108
108
  Note that you can also pass a raw `IO` descriptor, but this disables retries, as the library can't be sure if the descriptor is a file or pipe (which cannot be rewound).
109
109
 
110
+ ## Amazon Bedrock
111
+
112
+ Use the standard client with the Bedrock provider to call OpenAI models through Amazon Bedrock's OpenAI-compatible API. Add `aws-sdk-core` to your application for AWS credential discovery and SigV4 signing:
113
+
114
+ ```ruby
115
+ gem "openai"
116
+ gem "aws-sdk-core", "~> 3"
117
+ ```
118
+
119
+ With your normal AWS credentials configured, only the region is required:
120
+
121
+ ```ruby
122
+ require "openai"
123
+
124
+ client = OpenAI::Client.new(
125
+ provider: OpenAI::Providers.bedrock(region: "us-west-2")
126
+ )
127
+
128
+ response = client.responses.create(
129
+ model: ENV.fetch("BEDROCK_MODEL"),
130
+ input: "Say hello!"
131
+ )
132
+
133
+ puts(response.output_text)
134
+ ```
135
+
136
+ The provider uses the standard AWS credential chain, including environment credentials, `~/.aws/credentials`, `~/.aws/config`, `AWS_PROFILE`, named profiles, SSO and assume-role profiles, and workload credentials. Select a profile explicitly with:
137
+
138
+ ```ruby
139
+ client = OpenAI::Client.new(
140
+ provider: OpenAI::Providers.bedrock(
141
+ region: "us-west-2",
142
+ profile: "engineering"
143
+ )
144
+ )
145
+ ```
146
+
147
+ `AWS_BEARER_TOKEN_BEDROCK` and explicit Bedrock bearer credentials are also supported. Bearer authentication does not load or require `aws-sdk-core`:
148
+
149
+ ```ruby
150
+ client = OpenAI::Client.new(
151
+ provider: OpenAI::Providers.bedrock(
152
+ region: "us-west-2",
153
+ api_key: ENV.fetch("AWS_BEARER_TOKEN_BEDROCK")
154
+ )
155
+ )
156
+ ```
157
+
158
+ See [bedrock.md](bedrock.md) for authentication precedence, static and refreshable credentials, endpoint configuration, and SigV4 request constraints.
159
+
110
160
  ## Workload Identity Authentication
111
161
 
112
162
  For secure, automated environments like cloud-managed Kubernetes, Azure, and GCP, you can use workload identity authentication with short-lived tokens from cloud identity providers instead of long-lived API keys.
data/lib/openai/client.rb CHANGED
@@ -125,6 +125,8 @@ module OpenAI
125
125
  #
126
126
  # @return [Hash{String=>String}]
127
127
  private def auth_headers(security:)
128
+ return {} if @provider_runtime
129
+
128
130
  enabled_security = security.select { |_, enabled| enabled }
129
131
  headers = {bearer_auth:, admin_api_key_auth:}.slice(*enabled_security.keys).values.reduce({}, :merge)
130
132
  if headers.empty? && enabled_security.any?
@@ -166,6 +168,13 @@ module OpenAI
166
168
  true
167
169
  end
168
170
 
171
+ # @api private
172
+ private def prepare_request(request, redirect_count:, retry_count:)
173
+ preparer = @provider_runtime&.prepare_request
174
+ return super unless preparer
175
+ preparer.call(request)
176
+ end
177
+
169
178
  # @api private
170
179
  private def send_request(request, redirect_count:, retry_count:, send_retry_header:)
171
180
  return super unless @workload_identity_auth
@@ -218,6 +227,10 @@ module OpenAI
218
227
  #
219
228
  # @param webhook_secret [String, nil] Defaults to `ENV["OPENAI_WEBHOOK_SECRET"]`
220
229
  #
230
+ # @param provider [OpenAI::Provider, nil] Configure a supported
231
+ # third-party provider. Provider authentication and routing cannot be combined
232
+ # with top-level `api_key`, `admin_api_key`, `workload_identity`, or `base_url`.
233
+ #
221
234
  # @param base_url [String, nil] Override the default base URL for the API, e.g.,
222
235
  # `"https://api.example.com/v2/"`. Defaults to `ENV["OPENAI_BASE_URL"]`
223
236
  #
@@ -229,25 +242,65 @@ module OpenAI
229
242
  #
230
243
  # @param max_retry_delay [Float]
231
244
  def initialize(
232
- api_key: ENV["OPENAI_API_KEY"],
233
- admin_api_key: ENV["OPENAI_ADMIN_KEY"],
245
+ api_key: OpenAI::Internal::OMIT,
246
+ admin_api_key: OpenAI::Internal::OMIT,
234
247
  workload_identity: nil,
235
- organization: ENV["OPENAI_ORG_ID"],
236
- project: ENV["OPENAI_PROJECT_ID"],
237
- webhook_secret: ENV["OPENAI_WEBHOOK_SECRET"],
238
- base_url: ENV["OPENAI_BASE_URL"],
248
+ organization: OpenAI::Internal::OMIT,
249
+ project: OpenAI::Internal::OMIT,
250
+ webhook_secret: OpenAI::Internal::OMIT,
251
+ provider: nil,
252
+ base_url: OpenAI::Internal::OMIT,
239
253
  max_retries: self.class::DEFAULT_MAX_RETRIES,
240
254
  timeout: self.class::DEFAULT_TIMEOUT_IN_SECONDS,
241
255
  initial_retry_delay: self.class::DEFAULT_INITIAL_RETRY_DELAY,
242
256
  max_retry_delay: self.class::DEFAULT_MAX_RETRY_DELAY
243
257
  )
258
+ provider_runtime = nil
259
+ unless provider.nil?
260
+ provider_name = OpenAI::Internal::Provider.name(provider)
261
+ conflicts = {
262
+ api_key: api_key,
263
+ admin_api_key: admin_api_key,
264
+ workload_identity: workload_identity,
265
+ base_url: base_url
266
+ }.filter_map do |name, value|
267
+ name unless value.equal?(OpenAI::Internal::OMIT) || value.nil?
268
+ end
269
+ unless conflicts.empty?
270
+ formatted = conflicts.map { "`#{_1}`" }.join(", ")
271
+ message =
272
+ "`provider` cannot be combined with top-level #{formatted}. Move provider " \
273
+ "authentication and routing options into `#{provider_name}(...)`."
274
+ raise ArgumentError, message
275
+ end
276
+ provider_runtime = OpenAI::Internal::Provider.configure(provider)
277
+ end
278
+
279
+ api_key = ENV["OPENAI_API_KEY"] if api_key.equal?(OpenAI::Internal::OMIT) && provider_runtime.nil?
280
+ if admin_api_key.equal?(OpenAI::Internal::OMIT) && provider_runtime.nil?
281
+ admin_api_key = ENV["OPENAI_ADMIN_KEY"]
282
+ end
283
+ if organization.equal?(OpenAI::Internal::OMIT) && provider_runtime.nil?
284
+ organization = ENV["OPENAI_ORG_ID"]
285
+ end
286
+ project = ENV["OPENAI_PROJECT_ID"] if project.equal?(OpenAI::Internal::OMIT) && provider_runtime.nil?
287
+ webhook_secret = ENV["OPENAI_WEBHOOK_SECRET"] if webhook_secret.equal?(OpenAI::Internal::OMIT)
288
+ base_url = ENV["OPENAI_BASE_URL"] if base_url.equal?(OpenAI::Internal::OMIT) && provider_runtime.nil?
289
+
290
+ api_key = nil if api_key.equal?(OpenAI::Internal::OMIT)
291
+ admin_api_key = nil if admin_api_key.equal?(OpenAI::Internal::OMIT)
292
+ organization = nil if organization.equal?(OpenAI::Internal::OMIT)
293
+ project = nil if project.equal?(OpenAI::Internal::OMIT)
294
+ webhook_secret = nil if webhook_secret.equal?(OpenAI::Internal::OMIT)
295
+ base_url = provider_runtime.base_url if provider_runtime
296
+ base_url = nil if base_url.equal?(OpenAI::Internal::OMIT)
244
297
  base_url ||= "https://api.openai.com/v1"
245
298
 
246
299
  if !api_key.nil? && !workload_identity.nil?
247
300
  raise ArgumentError, "`api_key` and `workload_identity` are mutually exclusive"
248
301
  end
249
302
 
250
- if api_key.nil? && admin_api_key.nil? && workload_identity.nil?
303
+ if provider_runtime.nil? && api_key.nil? && admin_api_key.nil? && workload_identity.nil?
251
304
  raise ArgumentError,
252
305
  "Missing credentials. Please pass an `api_key`, `workload_identity`, `admin_api_key`, or set the `OPENAI_API_KEY` or `OPENAI_ADMIN_KEY` environment variable."
253
306
  end
@@ -256,7 +309,7 @@ module OpenAI
256
309
  "openai-organization" => (@organization = organization&.to_s),
257
310
  "openai-project" => (@project = project&.to_s)
258
311
  }
259
- custom_headers_env = ENV["OPENAI_CUSTOM_HEADERS"]
312
+ custom_headers_env = ENV["OPENAI_CUSTOM_HEADERS"] unless provider_runtime
260
313
  unless custom_headers_env.nil?
261
314
  parsed = {}
262
315
  custom_headers_env.split("\n").each do |line|
@@ -280,6 +333,7 @@ module OpenAI
280
333
  end
281
334
  @admin_api_key = admin_api_key&.to_s
282
335
  @webhook_secret = webhook_secret&.to_s
336
+ @provider_runtime = provider_runtime
283
337
 
284
338
  super(
285
339
  base_url: base_url,
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenAI
4
+ module Internal
5
+ # Private registry for OpenAI-owned provider configurations.
6
+ #
7
+ # Provider factories return opaque OpenAI::Provider instances whose public
8
+ # representation does not expose their definition.
9
+ module Provider
10
+ Runtime = Struct.new(:name, :base_url, :prepare_request, keyword_init: true)
11
+
12
+ class << self
13
+ # @api private
14
+ def create(definition)
15
+ OpenAI::Provider.send(:new, definition.freeze).freeze
16
+ end
17
+
18
+ # @api private
19
+ def name(provider) = definition(provider).name
20
+
21
+ # @api private
22
+ def configure(provider) = definition(provider).configure
23
+
24
+ private def definition(provider)
25
+ return provider.send(:definition) if provider.instance_of?(OpenAI::Provider)
26
+ raise ArgumentError, "Invalid provider. Providers must be created by an OpenAI provider factory."
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -232,6 +232,14 @@ module OpenAI
232
232
  # @return [Hash{String=>String}]
233
233
  private def auth_headers = {}
234
234
 
235
+ # Apply final per-attempt request transformations after retry headers are
236
+ # set and immediately before the request reaches the transport.
237
+ #
238
+ # @api private
239
+ private def prepare_request(request, **_context)
240
+ request
241
+ end
242
+
235
243
  # @api private
236
244
  #
237
245
  # @return [String]
@@ -371,6 +379,24 @@ module OpenAI
371
379
  (@initial_retry_delay * scale * jitter).clamp(0, @max_retry_delay)
372
380
  end
373
381
 
382
+ # @api private
383
+ private def raise_status_error!(url:, status:, headers:, response:, stream:)
384
+ decoded = Kernel.then do
385
+ OpenAI::Internal::Util.decode_content(headers, stream: stream, suppress_error: true)
386
+ ensure
387
+ self.class.reap_connection!(status, stream: stream)
388
+ end
389
+
390
+ raise OpenAI::Errors::APIStatusError.for(
391
+ url: url,
392
+ status: status,
393
+ headers: headers,
394
+ body: decoded,
395
+ request: nil,
396
+ response: response
397
+ )
398
+ end
399
+
374
400
  # @api private
375
401
  #
376
402
  # @param request [Hash{Symbol=>Object}] .
@@ -396,13 +422,23 @@ module OpenAI
396
422
  # @raise [OpenAI::Errors::APIError]
397
423
  # @return [Array(Integer, Net::HTTPResponse, Enumerable<String>)]
398
424
  def send_request(request, redirect_count:, retry_count:, send_retry_header:)
399
- url, headers, max_retries, timeout = request.fetch_values(:url, :headers, :max_retries, :timeout)
400
- input = {**request.except(:timeout), deadline: OpenAI::Internal::Util.monotonic_secs + timeout}
401
-
402
425
  if send_retry_header
403
- headers["x-stainless-retry-count"] = retry_count.to_s
426
+ request = request.merge(
427
+ headers: request.fetch(:headers).merge("x-stainless-retry-count" => retry_count.to_s)
428
+ )
404
429
  end
405
430
 
431
+ prepared_request = prepare_request(
432
+ request,
433
+ redirect_count: redirect_count,
434
+ retry_count: retry_count
435
+ )
436
+ url, max_retries, timeout = prepared_request.fetch_values(:url, :max_retries, :timeout)
437
+ input = {
438
+ **prepared_request.except(:timeout, :follow_redirects, :provider_auth),
439
+ deadline: OpenAI::Internal::Util.monotonic_secs + timeout
440
+ }
441
+
406
442
  begin
407
443
  status, response, stream = @requester.execute(input)
408
444
  rescue OpenAI::Errors::APIConnectionError => e
@@ -410,6 +446,25 @@ module OpenAI
410
446
  end
411
447
  headers = OpenAI::Internal::Util.normalized_headers(response&.each_header&.to_h)
412
448
 
449
+ terminal_status =
450
+ case status
451
+ in 300..399
452
+ prepared_request[:follow_redirects] == false
453
+ in (400..)
454
+ retry_count >= max_retries || !self.class.should_retry?(status, headers: headers)
455
+ else
456
+ false
457
+ end
458
+ if terminal_status
459
+ raise_status_error!(
460
+ url: url,
461
+ status: status,
462
+ headers: headers,
463
+ response: response,
464
+ stream: stream
465
+ )
466
+ end
467
+
413
468
  case status
414
469
  in ..299
415
470
  [status, response, stream]
@@ -421,30 +476,19 @@ module OpenAI
421
476
  in 300..399
422
477
  self.class.reap_connection!(status, stream: stream)
423
478
 
424
- request = self.class.follow_redirect(request, status: status, response_headers: headers)
479
+ redirected_request = self.class.follow_redirect(
480
+ prepared_request,
481
+ status: status,
482
+ response_headers: headers
483
+ )
425
484
  send_request(
426
- request,
485
+ redirected_request,
427
486
  redirect_count: redirect_count + 1,
428
487
  retry_count: retry_count,
429
488
  send_retry_header: send_retry_header
430
489
  )
431
490
  in OpenAI::Errors::APIConnectionError if retry_count >= max_retries
432
491
  raise status
433
- in (400..) if retry_count >= max_retries || !self.class.should_retry?(status, headers: headers)
434
- decoded = Kernel.then do
435
- OpenAI::Internal::Util.decode_content(headers, stream: stream, suppress_error: true)
436
- ensure
437
- self.class.reap_connection!(status, stream: stream)
438
- end
439
-
440
- raise OpenAI::Errors::APIStatusError.for(
441
- url: url,
442
- status: status,
443
- headers: headers,
444
- body: decoded,
445
- request: nil,
446
- response: response
447
- )
448
492
  in (400..) | OpenAI::Errors::APIConnectionError
449
493
  self.class.reap_connection!(status, stream: stream)
450
494
 
@@ -218,6 +218,90 @@ module OpenAI
218
218
  USER_ADDED = :"user.added"
219
219
  USER_UPDATED = :"user.updated"
220
220
  USER_DELETED = :"user.deleted"
221
+ TENANT_METADATA_UPDATED = :"tenant.metadata.updated"
222
+ TENANT_MICROSOFT_ENTRA_MAPPING_UPSERTED = :"tenant.microsoft_entra_mapping.upserted"
223
+ TENANT_MICROSOFT_ENTRA_MAPPING_DELETED = :"tenant.microsoft_entra_mapping.deleted"
224
+ TENANT_WORKLOAD_IDENTITY_PROVIDER_CREATED = :"tenant.workload_identity.provider.created"
225
+ TENANT_WORKLOAD_IDENTITY_PROVIDER_UPDATED = :"tenant.workload_identity.provider.updated"
226
+ TENANT_WORKLOAD_IDENTITY_PROVIDER_ARCHIVED = :"tenant.workload_identity.provider.archived"
227
+ TENANT_WORKLOAD_IDENTITY_MAPPING_CREATED = :"tenant.workload_identity.mapping.created"
228
+ TENANT_WORKLOAD_IDENTITY_MAPPING_UPDATED = :"tenant.workload_identity.mapping.updated"
229
+ TENANT_WORKLOAD_IDENTITY_MAPPING_ARCHIVED = :"tenant.workload_identity.mapping.archived"
230
+ TENANT_WORKLOAD_IDENTITY_BINDING_CREATED = :"tenant.workload_identity.binding.created"
231
+ TENANT_WORKLOAD_IDENTITY_PRINCIPAL_PROVISIONED = :"tenant.workload_identity.principal.provisioned"
232
+ TENANT_ADMIN_API_KEY_CREATED = :"tenant.admin_api_key.created"
233
+ TENANT_ADMIN_API_KEY_UPDATED = :"tenant.admin_api_key.updated"
234
+ TENANT_ADMIN_API_KEY_DELETED = :"tenant.admin_api_key.deleted"
235
+ TENANT_PROJECT_API_KEY_CREATED = :"tenant.project_api_key.created"
236
+ TENANT_CHATGPT_ACCESS_TOKEN_REVOKED = :"tenant.chatgpt_access_token.revoked"
237
+ TENANT_MIGRATION_COMPLETED = :"tenant.migration.completed"
238
+ TENANT_SSO_MIGRATED = :"tenant.sso.migrated"
239
+ TENANT_DOMAINS_MIGRATED = :"tenant.domains.migrated"
240
+ TENANT_SSO_CONNECTION_CREATED = :"tenant.sso_connection.created"
241
+ TENANT_SSO_CONNECTION_UPDATED = :"tenant.sso_connection.updated"
242
+ TENANT_SSO_CONNECTION_DELETED = :"tenant.sso_connection.deleted"
243
+ TENANT_SSO_CONNECTION_SETUP_STARTED = :"tenant.sso_connection.setup.started"
244
+ TENANT_POLICY_CREATED = :"tenant.policy.created"
245
+ TENANT_POLICY_UPDATED = :"tenant.policy.updated"
246
+ TENANT_POLICY_DELETED = :"tenant.policy.deleted"
247
+ TENANT_POLICY_ATTACHED = :"tenant.policy.attached"
248
+ TENANT_POLICY_DETACHED = :"tenant.policy.detached"
249
+ TENANT_PRINCIPAL_AUTHENTICATION_POLICY_RESOLVED = :"tenant.principal_authentication_policy.resolved"
250
+ TENANT_SCIM_SETUP_STARTED = :"tenant.scim.setup.started"
251
+ TENANT_SCIM_DELETION_REQUESTED = :"tenant.scim.deletion.requested"
252
+ TENANT_SCIM_DIRECTORY_CREATED = :"tenant.scim.directory.created"
253
+ TENANT_PRODUCT_ACCESS_POLICY_UPDATED = :"tenant.product_access_policy.updated"
254
+ TENANT_RESOURCE_SHARE_GRANT_CREATED = :"tenant.resource_share_grant.created"
255
+ TENANT_RESOURCE_SHARE_GRANT_UPDATED = :"tenant.resource_share_grant.updated"
256
+ TENANT_RESOURCE_SHARE_GRANT_ACCEPTED = :"tenant.resource_share_grant.accepted"
257
+ TENANT_RESOURCE_SHARE_GRANT_DECLINED = :"tenant.resource_share_grant.declined"
258
+ TENANT_RESOURCE_SHARE_GRANT_REVOKED = :"tenant.resource_share_grant.revoked"
259
+ TENANT_RESOURCE_SHARE_GRANT_DELETED = :"tenant.resource_share_grant.deleted"
260
+ TENANT_SERVICE_ACCOUNT_UPDATED = :"tenant.service_account.updated"
261
+ TENANT_SERVICE_ACCOUNT_DELETED = :"tenant.service_account.deleted"
262
+ TENANT_SERVICE_ACCOUNT_TOKEN_REVOKED = :"tenant.service_account.token.revoked"
263
+ TENANT_BILLING_OVERAGE_LIMIT_UPDATED = :"tenant.billing.overage_limit.updated"
264
+ TENANT_BILLING_ALERTS_UPDATED = :"tenant.billing.alerts.updated"
265
+ TENANT_BILLING_INFO_UPDATED = :"tenant.billing.info.updated"
266
+ TENANT_USAGE_LIMIT_WORKSPACE_UPDATED = :"tenant.usage_limit.workspace.updated"
267
+ TENANT_USAGE_LIMIT_GROUP_UPDATED = :"tenant.usage_limit.group.updated"
268
+ TENANT_USAGE_LIMIT_USER_UPDATED = :"tenant.usage_limit.user.updated"
269
+ TENANT_USAGE_LIMIT_INCREASE_REQUEST_UPDATED = :"tenant.usage_limit.increase_request.updated"
270
+ TENANT_USAGE_LIMIT_INCREASE_REQUEST_RESOLVED = :"tenant.usage_limit.increase_request.resolved"
271
+ TENANT_GROUP_CREATED = :"tenant.group.created"
272
+ TENANT_GROUP_UPDATED = :"tenant.group.updated"
273
+ TENANT_GROUP_DELETED = :"tenant.group.deleted"
274
+ TENANT_GROUP_MEMBER_ADDED = :"tenant.group.member.added"
275
+ TENANT_GROUP_MEMBER_REMOVED = :"tenant.group.member.removed"
276
+ TENANT_MIGRATION_ROLLOUT_STATUS_UPDATED = :"tenant.migration_rollout.status.updated"
277
+ TENANT_MIGRATION_ROLLOUT_TIER_UPDATED = :"tenant.migration_rollout.tier.updated"
278
+ TENANT_ROLE_METADATA_UPDATED = :"tenant.role.metadata.updated"
279
+ TENANT_CUSTOM_ROLE_CREATED = :"tenant.custom_role.created"
280
+ TENANT_CUSTOM_ROLE_UPDATED = :"tenant.custom_role.updated"
281
+ TENANT_CUSTOM_ROLE_DELETED = :"tenant.custom_role.deleted"
282
+ TENANT_ROLE_ASSIGNMENT_CREATED = :"tenant.role_assignment.created"
283
+ TENANT_ROLE_ASSIGNMENT_DELETED = :"tenant.role_assignment.deleted"
284
+ TENANT_RESOURCE_ROLE_ASSIGNMENT_CREATED = :"tenant.resource_role_assignment.created"
285
+ TENANT_RESOURCE_ROLE_ASSIGNMENT_DELETED = :"tenant.resource_role_assignment.deleted"
286
+ TENANT_RESOURCE_ACCESS_UPDATED = :"tenant.resource_access.updated"
287
+ TENANT_RESOURCE_ACCESS_DELETED = :"tenant.resource_access.deleted"
288
+ TENANT_SESSION_POLICY_CREATED = :"tenant.session_policy.created"
289
+ TENANT_SESSION_POLICY_UPDATED = :"tenant.session_policy.updated"
290
+ TENANT_SESSION_POLICY_DELETED = :"tenant.session_policy.deleted"
291
+ TENANT_SESSION_REVOCATION_STARTED = :"tenant.session_revocation.started"
292
+ TENANT_THIRD_PARTY_APP_POLICY_UPDATED = :"tenant.third_party_app_policy.updated"
293
+ TENANT_USER_ADDED = :"tenant.user.added"
294
+ TENANT_USER_UPDATED = :"tenant.user.updated"
295
+ TENANT_USER_REMOVED = :"tenant.user.removed"
296
+ TENANT_USER_LOOKED_UP = :"tenant.user.looked_up"
297
+ TENANT_USER_INVITED = :"tenant.user.invited"
298
+ TENANT_MEMBERSHIP_REVOKED = :"tenant.membership.revoked"
299
+ TENANT_API_ORGANIZATION_INVITE_UPSERTED = :"tenant.api_organization_invite.upserted"
300
+ TENANT_API_ORGANIZATION_INVITE_DELETED = :"tenant.api_organization_invite.deleted"
301
+ TENANT_CHATGPT_WORKSPACE_INVITE_UPSERTED = :"tenant.chatgpt_workspace_invite.upserted"
302
+ TENANT_MEMBERSHIP_ACCEPTED = :"tenant.membership.accepted"
303
+ TENANT_MEMBERSHIP_DECLINED = :"tenant.membership.declined"
304
+ TENANT_WORKSPACE_INVITE_EMAIL_SETTINGS_UPDATED = :"tenant.workspace_invite_email_settings.updated"
221
305
 
222
306
  # @!method self.values
223
307
  # @return [Array<Symbol>]
@@ -666,6 +666,90 @@ module OpenAI
666
666
  USER_ADDED = :"user.added"
667
667
  USER_UPDATED = :"user.updated"
668
668
  USER_DELETED = :"user.deleted"
669
+ TENANT_METADATA_UPDATED = :"tenant.metadata.updated"
670
+ TENANT_MICROSOFT_ENTRA_MAPPING_UPSERTED = :"tenant.microsoft_entra_mapping.upserted"
671
+ TENANT_MICROSOFT_ENTRA_MAPPING_DELETED = :"tenant.microsoft_entra_mapping.deleted"
672
+ TENANT_WORKLOAD_IDENTITY_PROVIDER_CREATED = :"tenant.workload_identity.provider.created"
673
+ TENANT_WORKLOAD_IDENTITY_PROVIDER_UPDATED = :"tenant.workload_identity.provider.updated"
674
+ TENANT_WORKLOAD_IDENTITY_PROVIDER_ARCHIVED = :"tenant.workload_identity.provider.archived"
675
+ TENANT_WORKLOAD_IDENTITY_MAPPING_CREATED = :"tenant.workload_identity.mapping.created"
676
+ TENANT_WORKLOAD_IDENTITY_MAPPING_UPDATED = :"tenant.workload_identity.mapping.updated"
677
+ TENANT_WORKLOAD_IDENTITY_MAPPING_ARCHIVED = :"tenant.workload_identity.mapping.archived"
678
+ TENANT_WORKLOAD_IDENTITY_BINDING_CREATED = :"tenant.workload_identity.binding.created"
679
+ TENANT_WORKLOAD_IDENTITY_PRINCIPAL_PROVISIONED = :"tenant.workload_identity.principal.provisioned"
680
+ TENANT_ADMIN_API_KEY_CREATED = :"tenant.admin_api_key.created"
681
+ TENANT_ADMIN_API_KEY_UPDATED = :"tenant.admin_api_key.updated"
682
+ TENANT_ADMIN_API_KEY_DELETED = :"tenant.admin_api_key.deleted"
683
+ TENANT_PROJECT_API_KEY_CREATED = :"tenant.project_api_key.created"
684
+ TENANT_CHATGPT_ACCESS_TOKEN_REVOKED = :"tenant.chatgpt_access_token.revoked"
685
+ TENANT_MIGRATION_COMPLETED = :"tenant.migration.completed"
686
+ TENANT_SSO_MIGRATED = :"tenant.sso.migrated"
687
+ TENANT_DOMAINS_MIGRATED = :"tenant.domains.migrated"
688
+ TENANT_SSO_CONNECTION_CREATED = :"tenant.sso_connection.created"
689
+ TENANT_SSO_CONNECTION_UPDATED = :"tenant.sso_connection.updated"
690
+ TENANT_SSO_CONNECTION_DELETED = :"tenant.sso_connection.deleted"
691
+ TENANT_SSO_CONNECTION_SETUP_STARTED = :"tenant.sso_connection.setup.started"
692
+ TENANT_POLICY_CREATED = :"tenant.policy.created"
693
+ TENANT_POLICY_UPDATED = :"tenant.policy.updated"
694
+ TENANT_POLICY_DELETED = :"tenant.policy.deleted"
695
+ TENANT_POLICY_ATTACHED = :"tenant.policy.attached"
696
+ TENANT_POLICY_DETACHED = :"tenant.policy.detached"
697
+ TENANT_PRINCIPAL_AUTHENTICATION_POLICY_RESOLVED = :"tenant.principal_authentication_policy.resolved"
698
+ TENANT_SCIM_SETUP_STARTED = :"tenant.scim.setup.started"
699
+ TENANT_SCIM_DELETION_REQUESTED = :"tenant.scim.deletion.requested"
700
+ TENANT_SCIM_DIRECTORY_CREATED = :"tenant.scim.directory.created"
701
+ TENANT_PRODUCT_ACCESS_POLICY_UPDATED = :"tenant.product_access_policy.updated"
702
+ TENANT_RESOURCE_SHARE_GRANT_CREATED = :"tenant.resource_share_grant.created"
703
+ TENANT_RESOURCE_SHARE_GRANT_UPDATED = :"tenant.resource_share_grant.updated"
704
+ TENANT_RESOURCE_SHARE_GRANT_ACCEPTED = :"tenant.resource_share_grant.accepted"
705
+ TENANT_RESOURCE_SHARE_GRANT_DECLINED = :"tenant.resource_share_grant.declined"
706
+ TENANT_RESOURCE_SHARE_GRANT_REVOKED = :"tenant.resource_share_grant.revoked"
707
+ TENANT_RESOURCE_SHARE_GRANT_DELETED = :"tenant.resource_share_grant.deleted"
708
+ TENANT_SERVICE_ACCOUNT_UPDATED = :"tenant.service_account.updated"
709
+ TENANT_SERVICE_ACCOUNT_DELETED = :"tenant.service_account.deleted"
710
+ TENANT_SERVICE_ACCOUNT_TOKEN_REVOKED = :"tenant.service_account.token.revoked"
711
+ TENANT_BILLING_OVERAGE_LIMIT_UPDATED = :"tenant.billing.overage_limit.updated"
712
+ TENANT_BILLING_ALERTS_UPDATED = :"tenant.billing.alerts.updated"
713
+ TENANT_BILLING_INFO_UPDATED = :"tenant.billing.info.updated"
714
+ TENANT_USAGE_LIMIT_WORKSPACE_UPDATED = :"tenant.usage_limit.workspace.updated"
715
+ TENANT_USAGE_LIMIT_GROUP_UPDATED = :"tenant.usage_limit.group.updated"
716
+ TENANT_USAGE_LIMIT_USER_UPDATED = :"tenant.usage_limit.user.updated"
717
+ TENANT_USAGE_LIMIT_INCREASE_REQUEST_UPDATED = :"tenant.usage_limit.increase_request.updated"
718
+ TENANT_USAGE_LIMIT_INCREASE_REQUEST_RESOLVED = :"tenant.usage_limit.increase_request.resolved"
719
+ TENANT_GROUP_CREATED = :"tenant.group.created"
720
+ TENANT_GROUP_UPDATED = :"tenant.group.updated"
721
+ TENANT_GROUP_DELETED = :"tenant.group.deleted"
722
+ TENANT_GROUP_MEMBER_ADDED = :"tenant.group.member.added"
723
+ TENANT_GROUP_MEMBER_REMOVED = :"tenant.group.member.removed"
724
+ TENANT_MIGRATION_ROLLOUT_STATUS_UPDATED = :"tenant.migration_rollout.status.updated"
725
+ TENANT_MIGRATION_ROLLOUT_TIER_UPDATED = :"tenant.migration_rollout.tier.updated"
726
+ TENANT_ROLE_METADATA_UPDATED = :"tenant.role.metadata.updated"
727
+ TENANT_CUSTOM_ROLE_CREATED = :"tenant.custom_role.created"
728
+ TENANT_CUSTOM_ROLE_UPDATED = :"tenant.custom_role.updated"
729
+ TENANT_CUSTOM_ROLE_DELETED = :"tenant.custom_role.deleted"
730
+ TENANT_ROLE_ASSIGNMENT_CREATED = :"tenant.role_assignment.created"
731
+ TENANT_ROLE_ASSIGNMENT_DELETED = :"tenant.role_assignment.deleted"
732
+ TENANT_RESOURCE_ROLE_ASSIGNMENT_CREATED = :"tenant.resource_role_assignment.created"
733
+ TENANT_RESOURCE_ROLE_ASSIGNMENT_DELETED = :"tenant.resource_role_assignment.deleted"
734
+ TENANT_RESOURCE_ACCESS_UPDATED = :"tenant.resource_access.updated"
735
+ TENANT_RESOURCE_ACCESS_DELETED = :"tenant.resource_access.deleted"
736
+ TENANT_SESSION_POLICY_CREATED = :"tenant.session_policy.created"
737
+ TENANT_SESSION_POLICY_UPDATED = :"tenant.session_policy.updated"
738
+ TENANT_SESSION_POLICY_DELETED = :"tenant.session_policy.deleted"
739
+ TENANT_SESSION_REVOCATION_STARTED = :"tenant.session_revocation.started"
740
+ TENANT_THIRD_PARTY_APP_POLICY_UPDATED = :"tenant.third_party_app_policy.updated"
741
+ TENANT_USER_ADDED = :"tenant.user.added"
742
+ TENANT_USER_UPDATED = :"tenant.user.updated"
743
+ TENANT_USER_REMOVED = :"tenant.user.removed"
744
+ TENANT_USER_LOOKED_UP = :"tenant.user.looked_up"
745
+ TENANT_USER_INVITED = :"tenant.user.invited"
746
+ TENANT_MEMBERSHIP_REVOKED = :"tenant.membership.revoked"
747
+ TENANT_API_ORGANIZATION_INVITE_UPSERTED = :"tenant.api_organization_invite.upserted"
748
+ TENANT_API_ORGANIZATION_INVITE_DELETED = :"tenant.api_organization_invite.deleted"
749
+ TENANT_CHATGPT_WORKSPACE_INVITE_UPSERTED = :"tenant.chatgpt_workspace_invite.upserted"
750
+ TENANT_MEMBERSHIP_ACCEPTED = :"tenant.membership.accepted"
751
+ TENANT_MEMBERSHIP_DECLINED = :"tenant.membership.declined"
752
+ TENANT_WORKSPACE_INVITE_EMAIL_SETTINGS_UPDATED = :"tenant.workspace_invite_email_settings.updated"
669
753
 
670
754
  # @!method self.values
671
755
  # @return [Array<Symbol>]
@@ -32,7 +32,7 @@ module OpenAI
32
32
  required :object, const: :"organization.project.service_account"
33
33
 
34
34
  # @!attribute role
35
- # `owner` or `member`
35
+ # `owner`, `member`, or `none`
36
36
  #
37
37
  # @return [Symbol, OpenAI::Models::Admin::Organization::Projects::ProjectServiceAccount::Role]
38
38
  required :role, enum: -> { OpenAI::Admin::Organization::Projects::ProjectServiceAccount::Role }
@@ -46,11 +46,11 @@ module OpenAI
46
46
  #
47
47
  # @param name [String] The name of the service account
48
48
  #
49
- # @param role [Symbol, OpenAI::Models::Admin::Organization::Projects::ProjectServiceAccount::Role] `owner` or `member`
49
+ # @param role [Symbol, OpenAI::Models::Admin::Organization::Projects::ProjectServiceAccount::Role] `owner`, `member`, or `none`
50
50
  #
51
51
  # @param object [Symbol, :"organization.project.service_account"] The object type, which is always `organization.project.service_account`
52
52
 
53
- # `owner` or `member`
53
+ # `owner`, `member`, or `none`
54
54
  #
55
55
  # @see OpenAI::Models::Admin::Organization::Projects::ProjectServiceAccount#role
56
56
  module Role
@@ -58,6 +58,7 @@ module OpenAI
58
58
 
59
59
  OWNER = :owner
60
60
  MEMBER = :member
61
+ NONE = :none
61
62
 
62
63
  # @!method self.values
63
64
  # @return [Array<Symbol>]
@@ -21,11 +21,19 @@ module OpenAI
21
21
  # @return [String]
22
22
  required :name, String
23
23
 
24
- # @!method initialize(project_id:, name:, request_options: {})
24
+ # @!attribute create_service_account_only
25
+ # Create the service account without default roles or an API key.
26
+ #
27
+ # @return [Boolean, nil]
28
+ optional :create_service_account_only, OpenAI::Internal::Type::Boolean, nil?: true
29
+
30
+ # @!method initialize(project_id:, name:, create_service_account_only: nil, request_options: {})
25
31
  # @param project_id [String]
26
32
  #
27
33
  # @param name [String] The name of the service account being created.
28
34
  #
35
+ # @param create_service_account_only [Boolean, nil] Create the service account without default roles or an API key.
36
+ #
29
37
  # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}]
30
38
  end
31
39
  end