openai 0.83.0 → 0.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/README.md +1 -1
- data/lib/openai/auth/workload_identity_auth.rb +17 -2
- data/lib/openai/client.rb +20 -6
- data/lib/openai/errors.rb +1 -1
- data/lib/openai/helpers/streaming/chat_completion_stream.rb +1 -2
- data/lib/openai/helpers/streaming/response_events.rb +2 -2
- data/lib/openai/helpers/streaming/response_stream.rb +73 -42
- data/lib/openai/helpers/structured_output/chat_completion_parser.rb +6 -0
- data/lib/openai/helpers/structured_output/response_parser.rb +1 -1
- data/lib/openai/internal/type/base_model.rb +2 -2
- data/lib/openai/internal/type/converter.rb +1 -1
- data/lib/openai/internal/util.rb +2 -2
- data/lib/openai/models/admin/organization/usage_costs_params.rb +10 -1
- data/lib/openai/models/batch.rb +4 -4
- data/lib/openai/models/beta/beta_response.rb +9 -12
- data/lib/openai/models/beta/beta_response_usage.rb +1 -12
- data/lib/openai/models/beta/beta_responses_client_event.rb +8 -12
- data/lib/openai/models/beta/response_compact_params.rb +7 -7
- data/lib/openai/models/beta/response_create_params.rb +8 -12
- data/lib/openai/models/chat/completion_create_params.rb +8 -8
- data/lib/openai/models/completion_usage.rb +1 -12
- data/lib/openai/models/eval_create_response.rb +1 -1
- data/lib/openai/models/eval_list_response.rb +1 -1
- data/lib/openai/models/eval_retrieve_response.rb +1 -1
- data/lib/openai/models/eval_update_response.rb +1 -1
- data/lib/openai/models/evals/create_eval_completions_run_data_source.rb +2 -2
- data/lib/openai/models/reasoning.rb +0 -2
- data/lib/openai/models/responses/response.rb +6 -7
- data/lib/openai/models/responses/response_compact_params.rb +7 -7
- data/lib/openai/models/responses/response_create_params.rb +5 -7
- data/lib/openai/models/responses/response_usage.rb +1 -12
- data/lib/openai/models/responses/responses_client_event.rb +5 -7
- data/lib/openai/resources/admin/organization/usage.rb +3 -1
- data/lib/openai/resources/beta/responses.rb +5 -5
- data/lib/openai/resources/chat/completions.rb +2 -2
- data/lib/openai/resources/responses.rb +7 -6
- data/lib/openai/version.rb +1 -1
- data/lib/openai.rb +1 -0
- data/rbi/openai/errors.rbi +1 -1
- data/rbi/openai/helpers/streaming/events.rbi +2 -2
- data/rbi/openai/helpers/streaming/response_stream.rbi +3 -3
- data/rbi/openai/models/admin/organization/usage_costs_params.rbi +15 -0
- data/rbi/openai/models/batch.rbi +6 -6
- data/rbi/openai/models/beta/beta_response.rbi +10 -15
- data/rbi/openai/models/beta/beta_response_usage.rbi +3 -13
- data/rbi/openai/models/beta/beta_responses_client_event.rbi +9 -15
- data/rbi/openai/models/beta/response_compact_params.rbi +9 -9
- data/rbi/openai/models/beta/response_create_params.rbi +9 -15
- data/rbi/openai/models/chat/completion_create_params.rbi +9 -9
- data/rbi/openai/models/completion_usage.rbi +0 -10
- data/rbi/openai/models/eval_create_response.rbi +1 -1
- data/rbi/openai/models/eval_list_response.rbi +1 -1
- data/rbi/openai/models/eval_retrieve_response.rbi +1 -1
- data/rbi/openai/models/eval_update_response.rbi +1 -1
- data/rbi/openai/models/evals/create_eval_completions_run_data_source.rbi +2 -2
- data/rbi/openai/models/reasoning.rbi +0 -2
- data/rbi/openai/models/responses/response.rbi +7 -10
- data/rbi/openai/models/responses/response_compact_params.rbi +9 -9
- data/rbi/openai/models/responses/response_create_params.rbi +6 -10
- data/rbi/openai/models/responses/response_usage.rbi +3 -13
- data/rbi/openai/models/responses/responses_client_event.rbi +6 -10
- data/rbi/openai/resources/admin/organization/usage.rbi +4 -0
- data/rbi/openai/resources/beta/responses.rbi +7 -11
- data/rbi/openai/resources/chat/completions.rbi +6 -6
- data/rbi/openai/resources/responses.rbi +9 -13
- data/sig/openai/errors.rbs +1 -1
- data/sig/openai/internal/transport/base_client.rbs +4 -19
- data/sig/openai/models/admin/organization/usage_costs_params.rbs +7 -0
- data/sig/openai/models/beta/beta_response.rbs +2 -1
- data/sig/openai/models/beta/beta_response_usage.rbs +3 -8
- data/sig/openai/models/completion_usage.rbs +0 -5
- data/sig/openai/models/responses/response.rbs +2 -1
- data/sig/openai/models/responses/response_usage.rbs +3 -8
- data/sig/openai/resources/admin/organization/usage.rbs +1 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 03f5297b1df9de7c2e182a5f76a72a5a15f2e9a34468b554eb92eb7e8022182b
|
|
4
|
+
data.tar.gz: 414ac43f94cee9591533b94c02d1d904cdd6a6ba0beb8694e88745b1b30dfad6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a2dda8c58eb47a26113b553b1428d23502d0c6740808954b740c0a5cf5dac361a798f6a14f963cff9d1230256cd800295017dc07489f7c6798f50a59c4066b1c
|
|
7
|
+
data.tar.gz: 72d931bd9cc9fa963b2f9d0d6f6e66078eb778456097d041850013b814ec20c3b5c9661a4b68c9fa2ea56a829aaaccc657e544a8cb68863f6c9ae4dd653aeb01
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.84.0](https://github.com/openai/openai-ruby/compare/v0.83.0...v0.84.0) (2026-09-02)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **api:** update usage APIs and documentation ([#566](https://github.com/openai/openai-ruby/issues/566)) ([caac1f0](https://github.com/openai/openai-ruby/commit/caac1f0d0932dff46e25f5879f5a1410425275e9))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* accept custom request hash in RBS ([#554](https://github.com/openai/openai-ruby/issues/554)) ([8d32aa1](https://github.com/openai/openai-ruby/commit/8d32aa1764ecff22d2cb3114fa1a4b6f7faa309b))
|
|
14
|
+
* avoid dispatching nil checks during coercion ([#552](https://github.com/openai/openai-ruby/issues/552)) ([c8d6d32](https://github.com/openai/openai-ruby/commit/c8d6d32e178563e38585d3ad928136e3c6f10ac1))
|
|
15
|
+
* avoid duplicate late-choice stream logprobs ([#564](https://github.com/openai/openai-ruby/issues/564)) ([2359a02](https://github.com/openai/openai-ruby/commit/2359a02dd22fbf599250aaa97e755863562abf53))
|
|
16
|
+
* delimit JSONL request records ([#553](https://github.com/openai/openai-ruby/issues/553)) ([dea0408](https://github.com/openai/openai-ruby/commit/dea04081076da3fde34f4a9b15f445dd92556b0f))
|
|
17
|
+
* enforce workload identity request deadlines ([#547](https://github.com/openai/openai-ruby/issues/547)) ([da421b5](https://github.com/openai/openai-ruby/commit/da421b507c24c35f62ff8679dd5c468ce8a0dab9))
|
|
18
|
+
* handle custom chat completion tool calls ([#556](https://github.com/openai/openai-ruby/issues/556)) ([dd49e31](https://github.com/openai/openai-ruby/commit/dd49e31134cf8dd1442f1b3fb428bab4dbc663d1))
|
|
19
|
+
* load YAML for BaseModel serialization ([#555](https://github.com/openai/openai-ruby/issues/555)) ([5420931](https://github.com/openai/openai-ruby/commit/54209313bca8a7159ad8ee4768678ac61b871d69))
|
|
20
|
+
* make error cause contract read-only ([#557](https://github.com/openai/openai-ruby/issues/557)) ([f3169ca](https://github.com/openai/openai-ruby/commit/f3169caae9a6115c3725c8d4da33e9ffb65085c5))
|
|
21
|
+
* preserve formatter path boundaries ([#559](https://github.com/openai/openai-ruby/issues/559)) ([f8b128c](https://github.com/openai/openai-ruby/commit/f8b128cf0db3198a297caec7e7ca8dfa991f16e8))
|
|
22
|
+
* respect StringIO cursor in multipart uploads ([#558](https://github.com/openai/openai-ruby/issues/558)) ([e8ea7c7](https://github.com/openai/openai-ruby/commit/e8ea7c73e7a233abaf7c919ce10117729918df5e))
|
|
23
|
+
* resume Responses streams from server-side cursors ([#548](https://github.com/openai/openai-ruby/issues/548)) ([3b88261](https://github.com/openai/openai-ruby/commit/3b88261e7cd9a8736028c1867c0c23d21aba54b5))
|
|
24
|
+
* support flattened responses typed function tools ([#550](https://github.com/openai/openai-ruby/issues/550)) ([ab16d33](https://github.com/openai/openai-ruby/commit/ab16d33e18c862608125cf12fac07e72702b8752))
|
|
25
|
+
* support structured chat output with typed function tools ([#546](https://github.com/openai/openai-ruby/issues/546)) ([087d1e2](https://github.com/openai/openai-ruby/commit/087d1e2041099342ed59be211259b81dce14392c))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Chores
|
|
29
|
+
|
|
30
|
+
* **deps-dev:** bump the development-dependencies group with 3 updates ([#560](https://github.com/openai/openai-ruby/issues/560)) ([f728e07](https://github.com/openai/openai-ruby/commit/f728e072a0d65e2d66b2e647d36843b76fd92606))
|
|
31
|
+
|
|
3
32
|
## [0.83.0](https://github.com/openai/openai-ruby/compare/v0.82.0...v0.83.0) (2026-08-27)
|
|
4
33
|
|
|
5
34
|
|
data/README.md
CHANGED
|
@@ -15,6 +15,12 @@ module OpenAI
|
|
|
15
15
|
DEFAULT_REFRESH_BUFFER_SECONDS = 1200
|
|
16
16
|
MAX_REJECTED_TOKEN_REFRESH_ATTEMPTS = 3
|
|
17
17
|
private_constant :MAX_REJECTED_TOKEN_REFRESH_ATTEMPTS
|
|
18
|
+
# Provider implementations wrap StandardError, but scheduler deadlines
|
|
19
|
+
# must cross that boundary before normalization to Timeout::Error.
|
|
20
|
+
# rubocop:disable Lint/InheritException
|
|
21
|
+
PROVIDER_DEADLINE_ERROR = Class.new(Exception)
|
|
22
|
+
# rubocop:enable Lint/InheritException
|
|
23
|
+
private_constant :PROVIDER_DEADLINE_ERROR
|
|
18
24
|
|
|
19
25
|
def initialize(
|
|
20
26
|
config,
|
|
@@ -274,10 +280,19 @@ module OpenAI
|
|
|
274
280
|
private def fetch_token_from_exchange(deadline:)
|
|
275
281
|
return @token_exchange.fetch(deadline: deadline) unless @token_exchange.nil?
|
|
276
282
|
|
|
277
|
-
|
|
283
|
+
message = "request timed out during workload identity authentication"
|
|
284
|
+
subject_token, token_type = begin
|
|
285
|
+
timeout = remaining_timeout(deadline)
|
|
286
|
+
Timeout.timeout(timeout, PROVIDER_DEADLINE_ERROR, message) do
|
|
287
|
+
[@config.provider.get_token, @config.provider.token_type]
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
rescue PROVIDER_DEADLINE_ERROR
|
|
291
|
+
raise Timeout::Error, message
|
|
292
|
+
end
|
|
293
|
+
|
|
278
294
|
check_deadline!(deadline)
|
|
279
295
|
|
|
280
|
-
token_type = @config.provider.token_type
|
|
281
296
|
subject_token_type = SUBJECT_TOKEN_TYPES.fetch(token_type) do
|
|
282
297
|
raise(
|
|
283
298
|
ArgumentError,
|
data/lib/openai/client.rb
CHANGED
|
@@ -18,6 +18,8 @@ module OpenAI
|
|
|
18
18
|
DEFAULT_MAX_RETRY_DELAY = 8.0
|
|
19
19
|
|
|
20
20
|
WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER = "workload-identity-auth"
|
|
21
|
+
WORKLOAD_IDENTITY_DEADLINE_ERROR = Class.new(Timeout::Error)
|
|
22
|
+
private_constant :WORKLOAD_IDENTITY_DEADLINE_ERROR
|
|
21
23
|
|
|
22
24
|
# @return [String, nil]
|
|
23
25
|
attr_reader :api_key
|
|
@@ -248,9 +250,9 @@ module OpenAI
|
|
|
248
250
|
|
|
249
251
|
# @api private
|
|
250
252
|
private def validate_retry_delay!(request, delay:)
|
|
251
|
-
deadline = request[:x509_request_context]&.fetch(:deadline)
|
|
253
|
+
deadline = request[:x509_request_context]&.fetch(:deadline) || request[:workload_identity_deadline]
|
|
252
254
|
if deadline && delay >= deadline - OpenAI::Internal::Util.monotonic_secs
|
|
253
|
-
raise
|
|
255
|
+
raise WORKLOAD_IDENTITY_DEADLINE_ERROR, "request timed out during workload identity authentication"
|
|
254
256
|
end
|
|
255
257
|
|
|
256
258
|
super
|
|
@@ -281,7 +283,8 @@ module OpenAI
|
|
|
281
283
|
request[:workload_identity_deadline] ||
|
|
282
284
|
request[:timeout]&.then { OpenAI::Internal::Util.monotonic_secs + _1 }
|
|
283
285
|
else
|
|
284
|
-
request[:
|
|
286
|
+
request[:workload_identity_deadline] ||
|
|
287
|
+
request[:timeout]&.then { OpenAI::Internal::Util.monotonic_secs + _1 }
|
|
285
288
|
end
|
|
286
289
|
|
|
287
290
|
request = request.merge(workload_identity_deadline: deadline)
|
|
@@ -359,8 +362,16 @@ module OpenAI
|
|
|
359
362
|
end
|
|
360
363
|
end
|
|
361
364
|
|
|
362
|
-
rescue Timeout::Error
|
|
363
|
-
|
|
365
|
+
rescue Timeout::Error => error
|
|
366
|
+
unless x509_request
|
|
367
|
+
raise unless error.is_a?(WORKLOAD_IDENTITY_DEADLINE_ERROR)
|
|
368
|
+
|
|
369
|
+
url = request.fetch(:url).dup
|
|
370
|
+
url.query = nil
|
|
371
|
+
url.fragment = nil
|
|
372
|
+
cause = Timeout::Error.new(error.message)
|
|
373
|
+
raise OpenAI::Errors::APITimeoutError.new(url: url, message: error.message), cause: cause
|
|
374
|
+
end
|
|
364
375
|
|
|
365
376
|
url = request.fetch(:url).dup
|
|
366
377
|
url.query = nil
|
|
@@ -443,7 +454,10 @@ module OpenAI
|
|
|
443
454
|
rescue Timeout::Error => e
|
|
444
455
|
raise if x509_transport?(@requester)
|
|
445
456
|
|
|
446
|
-
|
|
457
|
+
url = request.fetch(:url).dup
|
|
458
|
+
url.query = nil
|
|
459
|
+
url.fragment = nil
|
|
460
|
+
raise OpenAI::Errors::APITimeoutError.new(url: url, message: e.message)
|
|
447
461
|
end
|
|
448
462
|
|
|
449
463
|
# @api private
|
data/lib/openai/errors.rb
CHANGED
|
@@ -156,6 +156,7 @@ module OpenAI
|
|
|
156
156
|
insert_choice_snapshot!(completion_snapshot.choices, choice_snapshot)
|
|
157
157
|
else
|
|
158
158
|
update_existing_choice_snapshot(choice, choice_snapshot)
|
|
159
|
+
accumulate_logprobs!(choice.logprobs, choice_snapshot)
|
|
159
160
|
end
|
|
160
161
|
|
|
161
162
|
tool_calls_by_index = index_choice_snapshot!(choice_snapshot)
|
|
@@ -166,8 +167,6 @@ module OpenAI
|
|
|
166
167
|
end
|
|
167
168
|
|
|
168
169
|
parse_tool_calls!(choice.delta.tool_calls, tool_calls_by_index)
|
|
169
|
-
|
|
170
|
-
accumulate_logprobs!(choice.logprobs, choice_snapshot)
|
|
171
170
|
end
|
|
172
171
|
|
|
173
172
|
def create_new_choice_snapshot(choice)
|
|
@@ -4,7 +4,7 @@ module OpenAI
|
|
|
4
4
|
module Helpers
|
|
5
5
|
module Streaming
|
|
6
6
|
class ResponseTextDeltaEvent < OpenAI::Models::Responses::ResponseTextDeltaEvent
|
|
7
|
-
|
|
7
|
+
optional :snapshot, String, nil?: true
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
class ResponseTextDoneEvent < OpenAI::Models::Responses::ResponseTextDoneEvent
|
|
@@ -12,7 +12,7 @@ module OpenAI
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
class ResponseFunctionCallArgumentsDeltaEvent < OpenAI::Models::Responses::ResponseFunctionCallArgumentsDeltaEvent
|
|
15
|
-
|
|
15
|
+
optional :snapshot, String, nil?: true
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
class ResponseCompletedEvent < OpenAI::Models::Responses::ResponseCompletedEvent
|
|
@@ -13,7 +13,8 @@ module OpenAI
|
|
|
13
13
|
@last_response = raw_stream.last_response
|
|
14
14
|
@iterator = iterator
|
|
15
15
|
@state = ResponseStreamState.new(
|
|
16
|
-
text_format: text_format
|
|
16
|
+
text_format: text_format,
|
|
17
|
+
starting_after: starting_after
|
|
17
18
|
)
|
|
18
19
|
end
|
|
19
20
|
|
|
@@ -26,7 +27,7 @@ module OpenAI
|
|
|
26
27
|
OpenAI::Internal::Util.chain_fused(@iterator) do |yielder|
|
|
27
28
|
@iterator.each do |event|
|
|
28
29
|
case event
|
|
29
|
-
when OpenAI::
|
|
30
|
+
when OpenAI::Models::Responses::ResponseTextDeltaEvent
|
|
30
31
|
yielder << event.delta
|
|
31
32
|
end
|
|
32
33
|
end
|
|
@@ -80,10 +81,11 @@ module OpenAI
|
|
|
80
81
|
class ResponseStreamState
|
|
81
82
|
attr_reader :completed_response
|
|
82
83
|
|
|
83
|
-
def initialize(text_format:)
|
|
84
|
+
def initialize(text_format:, starting_after: nil)
|
|
84
85
|
@current_snapshot = nil
|
|
85
86
|
@completed_response = nil
|
|
86
87
|
@text_format = text_format
|
|
88
|
+
@resumed = !starting_after.nil?
|
|
87
89
|
end
|
|
88
90
|
|
|
89
91
|
def handle_event(event)
|
|
@@ -98,31 +100,43 @@ module OpenAI
|
|
|
98
100
|
|
|
99
101
|
case event
|
|
100
102
|
when OpenAI::Models::Responses::ResponseTextDeltaEvent
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
if @current_snapshot
|
|
104
|
+
output = @current_snapshot.output[event.output_index]
|
|
105
|
+
assert_type(output, :message)
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
107
|
+
content = output.content[event.content_index]
|
|
108
|
+
assert_type(content, :output_text)
|
|
109
|
+
events_to_yield <<
|
|
110
|
+
OpenAI::Streaming::ResponseTextDeltaEvent.new(
|
|
111
|
+
content_index: event.content_index,
|
|
112
|
+
delta: event.delta,
|
|
113
|
+
item_id: event.item_id,
|
|
114
|
+
output_index: event.output_index,
|
|
115
|
+
sequence_number: event.sequence_number,
|
|
116
|
+
type: event.type,
|
|
117
|
+
snapshot: content.text
|
|
118
|
+
)
|
|
119
|
+
else
|
|
120
|
+
# A server-directed resumed stream may begin after response.created.
|
|
121
|
+
# Without the omitted prefix, a snapshot would be incomplete and
|
|
122
|
+
# materializing every partial prefix would make streaming quadratic.
|
|
123
|
+
events_to_yield <<
|
|
124
|
+
OpenAI::Streaming::ResponseTextDeltaEvent.new(event.to_h.merge(snapshot: nil))
|
|
125
|
+
end
|
|
117
126
|
|
|
118
127
|
when OpenAI::Models::Responses::ResponseTextDoneEvent
|
|
119
|
-
|
|
120
|
-
|
|
128
|
+
text = if @current_snapshot
|
|
129
|
+
output = @current_snapshot.output[event.output_index]
|
|
130
|
+
assert_type(output, :message)
|
|
121
131
|
|
|
122
|
-
|
|
123
|
-
|
|
132
|
+
content = output.content[event.content_index]
|
|
133
|
+
assert_type(content, :output_text)
|
|
134
|
+
content.text
|
|
135
|
+
else
|
|
136
|
+
event.text
|
|
137
|
+
end
|
|
124
138
|
|
|
125
|
-
parsed = parse_structured_text(
|
|
139
|
+
parsed = parse_structured_text(text)
|
|
126
140
|
|
|
127
141
|
events_to_yield <<
|
|
128
142
|
OpenAI::Streaming::ResponseTextDoneEvent.new(
|
|
@@ -136,18 +150,26 @@ module OpenAI
|
|
|
136
150
|
)
|
|
137
151
|
|
|
138
152
|
when OpenAI::Models::Responses::ResponseFunctionCallArgumentsDeltaEvent
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
153
|
+
if @current_snapshot
|
|
154
|
+
output = @current_snapshot.output[event.output_index]
|
|
155
|
+
assert_type(output, :function_call)
|
|
156
|
+
events_to_yield <<
|
|
157
|
+
OpenAI::Streaming::ResponseFunctionCallArgumentsDeltaEvent.new(
|
|
158
|
+
delta: event.delta,
|
|
159
|
+
item_id: event.item_id,
|
|
160
|
+
output_index: event.output_index,
|
|
161
|
+
sequence_number: event.sequence_number,
|
|
162
|
+
type: event.type,
|
|
163
|
+
snapshot: output.arguments
|
|
164
|
+
)
|
|
165
|
+
else
|
|
166
|
+
# See the text-delta branch above: a partial server resume has no
|
|
167
|
+
# complete argument prefix from which to build a truthful snapshot.
|
|
168
|
+
events_to_yield <<
|
|
169
|
+
OpenAI::Streaming::ResponseFunctionCallArgumentsDeltaEvent.new(
|
|
170
|
+
event.to_h.merge(snapshot: nil)
|
|
171
|
+
)
|
|
172
|
+
end
|
|
151
173
|
|
|
152
174
|
when OpenAI::Models::Responses::ResponseCompletedEvent
|
|
153
175
|
events_to_yield <<
|
|
@@ -167,16 +189,25 @@ module OpenAI
|
|
|
167
189
|
|
|
168
190
|
def accumulate_event(event:, current_snapshot:)
|
|
169
191
|
if current_snapshot.nil?
|
|
170
|
-
|
|
192
|
+
if event.is_a?(OpenAI::Models::Responses::ResponseCreatedEvent)
|
|
193
|
+
# Use the converter to create a new, isolated copy of the response object.
|
|
194
|
+
# This ensures proper type validation and prevents shared object references.
|
|
195
|
+
return OpenAI::Internal::Type::Converter.coerce(
|
|
196
|
+
OpenAI::Models::Responses::Response,
|
|
197
|
+
event.response
|
|
198
|
+
)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
unless @resumed
|
|
171
202
|
raise "Expected first event to be response.created"
|
|
172
203
|
end
|
|
173
204
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
205
|
+
if event.is_a?(OpenAI::Models::Responses::ResponseCompletedEvent)
|
|
206
|
+
@completed_response = event.response
|
|
207
|
+
return event.response
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
return nil
|
|
180
211
|
end
|
|
181
212
|
|
|
182
213
|
case event
|
|
@@ -28,6 +28,8 @@ module OpenAI
|
|
|
28
28
|
|
|
29
29
|
raw[:choices]&.each do |choice|
|
|
30
30
|
choice.dig(:message, :tool_calls)&.each do |tool_call|
|
|
31
|
+
next if tool_call[:type] == "custom"
|
|
32
|
+
|
|
31
33
|
func = tool_call.fetch(:function)
|
|
32
34
|
next if (model = tool_models[func.fetch(:name)]).nil?
|
|
33
35
|
|
|
@@ -81,6 +83,10 @@ module OpenAI
|
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
85
|
parsed.dig(:response_format, :json_schema).store(:schema, model.to_json_schema)
|
|
86
|
+
else
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
case parsed
|
|
84
90
|
in {tools: Array => tools}
|
|
85
91
|
mapped = tools.map do |tool|
|
|
86
92
|
case tool
|
|
@@ -109,7 +109,7 @@ module OpenAI
|
|
|
109
109
|
parameters: tool.to_json_schema
|
|
110
110
|
}
|
|
111
111
|
in {type: :function, parameters: OpenAI::StructuredOutput::JsonSchemaConverter => params}
|
|
112
|
-
func = tool.fetch(:function)
|
|
112
|
+
func = tool.fetch(:function, tool)
|
|
113
113
|
name = func[:name] ||= params.name.split("::").last
|
|
114
114
|
tool_models.store(name, params)
|
|
115
115
|
func.update(parameters: params.to_json_schema)
|
|
@@ -119,7 +119,7 @@ module OpenAI
|
|
|
119
119
|
Kernel.then do
|
|
120
120
|
value = @data.fetch(name_sym) { const == OpenAI::Internal::OMIT ? nil : const }
|
|
121
121
|
state = OpenAI::Internal::Type::Converter.new_coerce_state(translate_names: false)
|
|
122
|
-
if (nilable || !required) &&
|
|
122
|
+
if (nilable || !required) && nil.equal?(value)
|
|
123
123
|
nil
|
|
124
124
|
else
|
|
125
125
|
OpenAI::Internal::Type::Converter.coerce(
|
|
@@ -321,7 +321,7 @@ module OpenAI
|
|
|
321
321
|
keys.delete(src_name)
|
|
322
322
|
|
|
323
323
|
state[:error] = nil
|
|
324
|
-
converted = if
|
|
324
|
+
converted = if nil.equal?(item) && (nilable || !required)
|
|
325
325
|
exactness[nilable ? :yes : :maybe] += 1
|
|
326
326
|
nil
|
|
327
327
|
else
|
data/lib/openai/internal/util.rb
CHANGED
|
@@ -510,7 +510,7 @@ module OpenAI
|
|
|
510
510
|
IO.copy_stream(val, y)
|
|
511
511
|
in StringIO
|
|
512
512
|
y << format(content_line, content_type || "application/octet-stream")
|
|
513
|
-
y << val.string
|
|
513
|
+
y << (val.string.byteslice(val.pos..) || "")
|
|
514
514
|
in -> { primitive?(_1) }
|
|
515
515
|
y << format(content_line, content_type || "text/plain")
|
|
516
516
|
y << val.to_s
|
|
@@ -630,7 +630,7 @@ module OpenAI
|
|
|
630
630
|
in [OpenAI::Internal::Util::JSON_CONTENT, Hash | Array | -> { primitive?(_1) }]
|
|
631
631
|
[headers, JSON.generate(body)]
|
|
632
632
|
in [OpenAI::Internal::Util::JSONL_CONTENT, Enumerable] unless OpenAI::Internal::Type::FileInput === body
|
|
633
|
-
[headers, body.lazy.map { JSON.generate(_1) }]
|
|
633
|
+
[headers, body.lazy.map { "#{JSON.generate(_1)}\n" }]
|
|
634
634
|
in [%r{^multipart/form-data}, Hash | OpenAI::Internal::Type::FileInput]
|
|
635
635
|
boundary, strio = encode_multipart_streaming(body)
|
|
636
636
|
headers = {**headers, "content-type" => "#{content_type}; boundary=#{boundary}"}
|
|
@@ -51,6 +51,13 @@ module OpenAI
|
|
|
51
51
|
# @return [Integer, nil]
|
|
52
52
|
optional :limit, Integer
|
|
53
53
|
|
|
54
|
+
# @!attribute line_items
|
|
55
|
+
# Return only costs for these exact line item names. Each value must match the
|
|
56
|
+
# complete `line_item` value, for example `gpt-5.6-sol, input_tokens`.
|
|
57
|
+
#
|
|
58
|
+
# @return [Array<String>, nil]
|
|
59
|
+
optional :line_items, OpenAI::Internal::Type::ArrayOf[String]
|
|
60
|
+
|
|
54
61
|
# @!attribute page
|
|
55
62
|
# A cursor for use in pagination. Corresponding to the `next_page` field from the
|
|
56
63
|
# previous response.
|
|
@@ -64,7 +71,7 @@ module OpenAI
|
|
|
64
71
|
# @return [Array<String>, nil]
|
|
65
72
|
optional :project_ids, OpenAI::Internal::Type::ArrayOf[String]
|
|
66
73
|
|
|
67
|
-
# @!method initialize(start_time:, api_key_ids: nil, bucket_width: nil, end_time: nil, group_by: nil, limit: nil, page: nil, project_ids: nil, request_options: {})
|
|
74
|
+
# @!method initialize(start_time:, api_key_ids: nil, bucket_width: nil, end_time: nil, group_by: nil, limit: nil, line_items: nil, page: nil, project_ids: nil, request_options: {})
|
|
68
75
|
# Some parameter documentations has been truncated, see
|
|
69
76
|
# {OpenAI::Models::Admin::Organization::UsageCostsParams} for more details.
|
|
70
77
|
#
|
|
@@ -80,6 +87,8 @@ module OpenAI
|
|
|
80
87
|
#
|
|
81
88
|
# @param limit [Integer] A limit on the number of buckets to be returned. Limit can range between 1 and 1
|
|
82
89
|
#
|
|
90
|
+
# @param line_items [Array<String>] Return only costs for these exact line item names. Each value must match the com
|
|
91
|
+
#
|
|
83
92
|
# @param page [String] A cursor for use in pagination. Corresponding to the `next_page` field from the
|
|
84
93
|
#
|
|
85
94
|
# @param project_ids [Array<String>] Return only costs for these projects.
|
data/lib/openai/models/batch.rb
CHANGED
|
@@ -116,9 +116,9 @@ module OpenAI
|
|
|
116
116
|
optional :metadata, OpenAI::Internal::Type::HashOf[String], nil?: true
|
|
117
117
|
|
|
118
118
|
# @!attribute model
|
|
119
|
-
# Model ID used to process the batch, like `gpt-5-
|
|
120
|
-
#
|
|
121
|
-
#
|
|
119
|
+
# Model ID used to process the batch, like `gpt-5.6-sol`. OpenAI offers a wide
|
|
120
|
+
# range of models with different capabilities, performance characteristics, and
|
|
121
|
+
# price points. Refer to the
|
|
122
122
|
# [model guide](https://platform.openai.com/docs/models) to browse and compare
|
|
123
123
|
# available models.
|
|
124
124
|
#
|
|
@@ -183,7 +183,7 @@ module OpenAI
|
|
|
183
183
|
#
|
|
184
184
|
# @param metadata [Hash{Symbol=>String}, nil] Set of 16 key-value pairs that can be attached to an object. This can be
|
|
185
185
|
#
|
|
186
|
-
# @param model [String] Model ID used to process the batch, like `gpt-5-
|
|
186
|
+
# @param model [String] Model ID used to process the batch, like `gpt-5.6-sol`. OpenAI
|
|
187
187
|
#
|
|
188
188
|
# @param output_file_id [String] The ID of the file containing the outputs of successfully executed requests.
|
|
189
189
|
#
|
|
@@ -53,9 +53,9 @@ module OpenAI
|
|
|
53
53
|
required :metadata, OpenAI::Internal::Type::HashOf[String], nil?: true
|
|
54
54
|
|
|
55
55
|
# @!attribute model
|
|
56
|
-
# Model ID used to generate the response, like `gpt-
|
|
57
|
-
#
|
|
58
|
-
#
|
|
56
|
+
# Model ID used to generate the response, like `gpt-5.6-sol`. OpenAI offers a wide
|
|
57
|
+
# range of models with different capabilities, performance characteristics, and
|
|
58
|
+
# price points. Refer to the
|
|
59
59
|
# [model guide](https://platform.openai.com/docs/models) to browse and compare
|
|
60
60
|
# available models.
|
|
61
61
|
#
|
|
@@ -242,8 +242,6 @@ module OpenAI
|
|
|
242
242
|
)
|
|
243
243
|
|
|
244
244
|
# @!attribute reasoning
|
|
245
|
-
# **gpt-5 and o-series models only**
|
|
246
|
-
#
|
|
247
245
|
# Configuration options for
|
|
248
246
|
# [reasoning models](https://platform.openai.com/docs/guides/reasoning).
|
|
249
247
|
#
|
|
@@ -362,7 +360,7 @@ module OpenAI
|
|
|
362
360
|
#
|
|
363
361
|
# @param metadata [Hash{Symbol=>String}, nil] Set of 16 key-value pairs that can be attached to an object. This can be
|
|
364
362
|
#
|
|
365
|
-
# @param model [Symbol, String, OpenAI::Models::Beta::BetaResponse::Model] Model ID used to generate the response, like `gpt-
|
|
363
|
+
# @param model [Symbol, String, OpenAI::Models::Beta::BetaResponse::Model] Model ID used to generate the response, like `gpt-5.6-sol`. OpenAI
|
|
366
364
|
#
|
|
367
365
|
# @param output [Array<OpenAI::Models::Beta::BetaResponseOutputMessage, OpenAI::Models::Beta::BetaResponseFileSearchToolCall, OpenAI::Models::Beta::BetaResponseFunctionToolCall, OpenAI::Models::Beta::BetaResponseFunctionToolCallOutputItem, OpenAI::Models::Beta::BetaResponseOutputItem::AgentMessage, OpenAI::Models::Beta::BetaResponseOutputItem::MultiAgentCall, OpenAI::Models::Beta::BetaResponseOutputItem::MultiAgentCallOutput, OpenAI::Models::Beta::BetaResponseFunctionWebSearch, OpenAI::Models::Beta::BetaResponseComputerToolCall, OpenAI::Models::Beta::BetaResponseComputerToolCallOutputItem, OpenAI::Models::Beta::BetaResponseReasoningItem, OpenAI::Models::Beta::BetaResponseOutputItem::Program, OpenAI::Models::Beta::BetaResponseOutputItem::ProgramOutput, OpenAI::Models::Beta::BetaResponseToolSearchCall, OpenAI::Models::Beta::BetaResponseToolSearchOutputItem, OpenAI::Models::Beta::BetaResponseOutputItem::AdditionalTools, OpenAI::Models::Beta::BetaResponseCompactionItem, OpenAI::Models::Beta::BetaResponseOutputItem::ImageGenerationCall, OpenAI::Models::Beta::BetaResponseCodeInterpreterToolCall, OpenAI::Models::Beta::BetaResponseOutputItem::LocalShellCall, OpenAI::Models::Beta::BetaResponseOutputItem::LocalShellCallOutput, OpenAI::Models::Beta::BetaResponseFunctionShellToolCall, OpenAI::Models::Beta::BetaResponseFunctionShellToolCallOutput, OpenAI::Models::Beta::BetaResponseApplyPatchToolCall, OpenAI::Models::Beta::BetaResponseApplyPatchToolCallOutput, OpenAI::Models::Beta::BetaResponseOutputItem::McpCall, OpenAI::Models::Beta::BetaResponseOutputItem::McpListTools, OpenAI::Models::Beta::BetaResponseOutputItem::McpApprovalRequest, OpenAI::Models::Beta::BetaResponseOutputItem::McpApprovalResponse, OpenAI::Models::Beta::BetaResponseCustomToolCall, OpenAI::Models::Beta::BetaResponseCustomToolCallOutputItem>] An array of content items generated by the model.
|
|
368
366
|
#
|
|
@@ -398,7 +396,7 @@ module OpenAI
|
|
|
398
396
|
#
|
|
399
397
|
# @param prompt_cache_retention [Symbol, OpenAI::Models::Beta::BetaResponse::PromptCacheRetention, nil] Deprecated. Use `prompt_cache_options.ttl` instead.
|
|
400
398
|
#
|
|
401
|
-
# @param reasoning [OpenAI::Models::Beta::BetaResponse::Reasoning, nil]
|
|
399
|
+
# @param reasoning [OpenAI::Models::Beta::BetaResponse::Reasoning, nil] Configuration options for
|
|
402
400
|
#
|
|
403
401
|
# @param safety_identifier [String, nil] A stable identifier used to help detect users of your application that may be vi
|
|
404
402
|
#
|
|
@@ -438,6 +436,7 @@ module OpenAI
|
|
|
438
436
|
extend OpenAI::Internal::Type::Enum
|
|
439
437
|
|
|
440
438
|
MAX_OUTPUT_TOKENS = :max_output_tokens
|
|
439
|
+
MAX_MESSAGES = :max_messages
|
|
441
440
|
CONTENT_FILTER = :content_filter
|
|
442
441
|
|
|
443
442
|
# @!method self.values
|
|
@@ -472,9 +471,9 @@ module OpenAI
|
|
|
472
471
|
]
|
|
473
472
|
end
|
|
474
473
|
|
|
475
|
-
# Model ID used to generate the response, like `gpt-
|
|
476
|
-
#
|
|
477
|
-
#
|
|
474
|
+
# Model ID used to generate the response, like `gpt-5.6-sol`. OpenAI offers a wide
|
|
475
|
+
# range of models with different capabilities, performance characteristics, and
|
|
476
|
+
# price points. Refer to the
|
|
478
477
|
# [model guide](https://platform.openai.com/docs/models) to browse and compare
|
|
479
478
|
# available models.
|
|
480
479
|
#
|
|
@@ -1290,8 +1289,6 @@ module OpenAI
|
|
|
1290
1289
|
# Some parameter documentations has been truncated, see
|
|
1291
1290
|
# {OpenAI::Models::Beta::BetaResponse::Reasoning} for more details.
|
|
1292
1291
|
#
|
|
1293
|
-
# **gpt-5 and o-series models only**
|
|
1294
|
-
#
|
|
1295
1292
|
# Configuration options for
|
|
1296
1293
|
# [reasoning models](https://platform.openai.com/docs/guides/reasoning).
|
|
1297
1294
|
#
|
|
@@ -34,16 +34,7 @@ module OpenAI
|
|
|
34
34
|
# @return [Integer]
|
|
35
35
|
required :total_tokens, Integer
|
|
36
36
|
|
|
37
|
-
# @!
|
|
38
|
-
# Compute units for the request. Currently null when available.
|
|
39
|
-
#
|
|
40
|
-
# @return [Integer, nil]
|
|
41
|
-
optional :compute_units, Integer, nil?: true
|
|
42
|
-
|
|
43
|
-
# @!method initialize(input_tokens:, input_tokens_details:, output_tokens:, output_tokens_details:, total_tokens:, compute_units: nil)
|
|
44
|
-
# Some parameter documentations has been truncated, see
|
|
45
|
-
# {OpenAI::Models::Beta::BetaResponseUsage} for more details.
|
|
46
|
-
#
|
|
37
|
+
# @!method initialize(input_tokens:, input_tokens_details:, output_tokens:, output_tokens_details:, total_tokens:)
|
|
47
38
|
# Represents token usage details including input tokens, output tokens, a
|
|
48
39
|
# breakdown of output tokens, and the total tokens used.
|
|
49
40
|
#
|
|
@@ -56,8 +47,6 @@ module OpenAI
|
|
|
56
47
|
# @param output_tokens_details [OpenAI::Models::Beta::BetaResponseUsage::OutputTokensDetails] A detailed breakdown of the output tokens.
|
|
57
48
|
#
|
|
58
49
|
# @param total_tokens [Integer] The total number of tokens used.
|
|
59
|
-
#
|
|
60
|
-
# @param compute_units [Integer, nil] Compute units for the request. Currently null when available.
|
|
61
50
|
|
|
62
51
|
# @see OpenAI::Models::Beta::BetaResponseUsage#input_tokens_details
|
|
63
52
|
class InputTokensDetails < OpenAI::Internal::Type::BaseModel
|