anthropic 1.1.1 → 1.2.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 +45 -0
- data/README.md +32 -16
- data/lib/anthropic/errors.rb +22 -0
- data/lib/anthropic/helpers/streaming/events.rb +141 -0
- data/lib/anthropic/helpers/streaming/message_stream.rb +238 -0
- data/lib/anthropic/helpers/streaming.rb +37 -0
- data/lib/anthropic/helpers/vertex/client.rb +4 -1
- data/lib/anthropic/internal/stream.rb +4 -2
- data/lib/anthropic/internal/transport/base_client.rb +10 -2
- data/lib/anthropic/internal/type/array_of.rb +6 -1
- data/lib/anthropic/internal/type/base_model.rb +77 -23
- data/lib/anthropic/internal/type/base_stream.rb +3 -1
- data/lib/anthropic/internal/type/boolean.rb +7 -1
- data/lib/anthropic/internal/type/converter.rb +42 -34
- data/lib/anthropic/internal/type/enum.rb +16 -5
- data/lib/anthropic/internal/type/file_input.rb +6 -1
- data/lib/anthropic/internal/type/hash_of.rb +6 -1
- data/lib/anthropic/internal/type/union.rb +17 -9
- data/lib/anthropic/internal/type/unknown.rb +7 -1
- data/lib/anthropic/internal/util.rb +8 -9
- data/lib/anthropic/models/beta/beta_base64_pdf_block.rb +1 -65
- data/lib/anthropic/models/beta/beta_citation_search_result_location.rb +55 -0
- data/lib/anthropic/models/beta/beta_citation_search_result_location_param.rb +55 -0
- data/lib/anthropic/models/beta/beta_citations_delta.rb +5 -3
- data/lib/anthropic/models/beta/beta_content_block.rb +5 -5
- data/lib/anthropic/models/beta/beta_content_block_param.rb +20 -17
- data/lib/anthropic/models/beta/beta_message.rb +6 -2
- data/lib/anthropic/models/beta/beta_message_param.rb +3 -3
- data/lib/anthropic/models/beta/beta_raw_content_block_start_event.rb +7 -7
- data/lib/anthropic/models/beta/beta_request_document_block.rb +75 -0
- data/lib/anthropic/models/beta/beta_search_result_block_param.rb +55 -0
- data/lib/anthropic/models/beta/beta_text_block.rb +2 -2
- data/lib/anthropic/models/beta/beta_text_block_param.rb +2 -2
- data/lib/anthropic/models/beta/beta_text_citation.rb +3 -1
- data/lib/anthropic/models/beta/beta_text_citation_param.rb +3 -1
- data/lib/anthropic/models/beta/beta_tool.rb +7 -1
- data/lib/anthropic/models/beta/beta_tool_result_block_param.rb +6 -4
- data/lib/anthropic/models/beta/beta_tool_union.rb +7 -7
- data/lib/anthropic/models/beta/message_count_tokens_params.rb +16 -10
- data/lib/anthropic/models/beta/message_create_params.rb +9 -3
- data/lib/anthropic/models/beta/messages/batch_create_params.rb +9 -3
- data/lib/anthropic/models/content_block.rb +5 -5
- data/lib/anthropic/models/content_block_param.rb +11 -11
- data/lib/anthropic/models/message.rb +6 -2
- data/lib/anthropic/models/message_count_tokens_params.rb +9 -3
- data/lib/anthropic/models/message_count_tokens_tool.rb +35 -1
- data/lib/anthropic/models/message_create_params.rb +9 -3
- data/lib/anthropic/models/message_param.rb +3 -3
- data/lib/anthropic/models/messages/batch_create_params.rb +9 -3
- data/lib/anthropic/models/model.rb +6 -0
- data/lib/anthropic/models/raw_content_block_start_event.rb +7 -7
- data/lib/anthropic/models/tool.rb +7 -1
- data/lib/anthropic/models/tool_union.rb +34 -1
- data/lib/anthropic/models/tool_use_block.rb +6 -0
- data/lib/anthropic/models.rb +4 -4
- data/lib/anthropic/resources/beta/messages.rb +5 -5
- data/lib/anthropic/resources/messages.rb +68 -7
- data/lib/anthropic/streaming.rb +5 -0
- data/lib/anthropic/version.rb +1 -1
- data/lib/anthropic.rb +8 -0
- data/rbi/anthropic/errors.rbi +16 -0
- data/rbi/anthropic/helpers/streaming/events.rbi +85 -0
- data/rbi/anthropic/helpers/streaming/message_stream.rbi +59 -0
- data/rbi/anthropic/internal/type/base_stream.rbi +8 -1
- data/rbi/anthropic/internal/type/boolean.rbi +2 -0
- data/rbi/anthropic/internal/type/converter.rbi +15 -15
- data/rbi/anthropic/internal/type/union.rbi +5 -0
- data/rbi/anthropic/internal/type/unknown.rbi +2 -0
- data/rbi/anthropic/internal/util.rbi +2 -0
- data/rbi/anthropic/models/beta/beta_base64_pdf_block.rbi +1 -128
- data/rbi/anthropic/models/beta/beta_citation_search_result_location.rbi +78 -0
- data/rbi/anthropic/models/beta/beta_citation_search_result_location_param.rbi +79 -0
- data/rbi/anthropic/models/beta/beta_citations_delta.rbi +4 -2
- data/rbi/anthropic/models/beta/beta_content_block.rbi +3 -3
- data/rbi/anthropic/models/beta/beta_content_block_param.rbi +8 -7
- data/rbi/anthropic/models/beta/beta_message.rbi +11 -3
- data/rbi/anthropic/models/beta/beta_raw_content_block_start_event.rbi +6 -6
- data/rbi/anthropic/models/beta/beta_request_document_block.rbi +140 -0
- data/rbi/anthropic/models/beta/beta_search_result_block_param.rbi +91 -0
- data/rbi/anthropic/models/beta/beta_text_block.rbi +2 -1
- data/rbi/anthropic/models/beta/beta_text_block_param.rbi +6 -3
- data/rbi/anthropic/models/beta/beta_text_citation.rbi +2 -1
- data/rbi/anthropic/models/beta/beta_text_citation_param.rbi +2 -1
- data/rbi/anthropic/models/beta/beta_tool.rbi +14 -5
- data/rbi/anthropic/models/beta/beta_tool_result_block_param.rbi +2 -1
- data/rbi/anthropic/models/beta/beta_tool_union.rbi +5 -5
- data/rbi/anthropic/models/beta/message_count_tokens_params.rbi +39 -27
- data/rbi/anthropic/models/beta/message_create_params.rbi +34 -22
- data/rbi/anthropic/models/beta/messages/batch_create_params.rbi +34 -22
- data/rbi/anthropic/models/content_block.rbi +3 -3
- data/rbi/anthropic/models/content_block_param.rbi +5 -5
- data/rbi/anthropic/models/message.rbi +11 -3
- data/rbi/anthropic/models/message_count_tokens_params.rbi +18 -2
- data/rbi/anthropic/models/message_count_tokens_tool.rbi +61 -0
- data/rbi/anthropic/models/message_create_params.rbi +18 -2
- data/rbi/anthropic/models/messages/batch_create_params.rbi +18 -2
- data/rbi/anthropic/models/raw_content_block_start_event.rbi +6 -6
- data/rbi/anthropic/models/tool.rbi +16 -5
- data/rbi/anthropic/models/tool_union.rbi +61 -0
- data/rbi/anthropic/resources/beta/messages.rbi +36 -18
- data/rbi/anthropic/resources/messages.rbi +293 -3
- data/rbi/anthropic/streaming.rbi +5 -0
- data/sig/anthropic/errors.rbs +9 -0
- data/sig/anthropic/helpers/streaming/events.rbs +119 -0
- data/sig/anthropic/helpers/streaming/message_stream.rbs +55 -0
- data/sig/anthropic/internal/type/base_stream.rbs +4 -0
- data/sig/anthropic/internal/type/converter.rbs +7 -1
- data/sig/anthropic/models/beta/beta_base64_pdf_block.rbs +1 -58
- data/sig/anthropic/models/beta/beta_citation_search_result_location.rbs +54 -0
- data/sig/anthropic/models/beta/beta_citation_search_result_location_param.rbs +54 -0
- data/sig/anthropic/models/beta/beta_citations_delta.rbs +1 -0
- data/sig/anthropic/models/beta/beta_content_block.rbs +2 -2
- data/sig/anthropic/models/beta/beta_content_block_param.rbs +9 -8
- data/sig/anthropic/models/beta/beta_raw_content_block_start_event.rbs +2 -2
- data/sig/anthropic/models/beta/beta_request_document_block.rbs +66 -0
- data/sig/anthropic/models/beta/beta_search_result_block_param.rbs +53 -0
- data/sig/anthropic/models/beta/beta_text_citation.rbs +1 -0
- data/sig/anthropic/models/beta/beta_text_citation_param.rbs +1 -0
- data/sig/anthropic/models/beta/beta_tool.rbs +14 -3
- data/sig/anthropic/models/beta/beta_tool_result_block_param.rbs +1 -0
- data/sig/anthropic/models/beta/beta_tool_union.rbs +4 -4
- data/sig/anthropic/models/beta/message_count_tokens_params.rbs +4 -4
- data/sig/anthropic/models/content_block.rbs +2 -2
- data/sig/anthropic/models/content_block_param.rbs +5 -5
- data/sig/anthropic/models/message_count_tokens_tool.rbs +28 -0
- data/sig/anthropic/models/raw_content_block_start_event.rbs +2 -2
- data/sig/anthropic/models/tool.rbs +14 -3
- data/sig/anthropic/models/tool_union.rbs +28 -0
- data/sig/anthropic/streaming.rbs +3 -0
- metadata +26 -3
@@ -23,13 +23,15 @@ module Anthropic
|
|
23
23
|
case msg
|
24
24
|
in {event: "completion", data: String => data}
|
25
25
|
decoded = JSON.parse(data, symbolize_names: true)
|
26
|
-
|
26
|
+
unwrapped = Anthropic::Internal::Util.dig(decoded, @unwrap)
|
27
|
+
y << Anthropic::Internal::Type::Converter.coerce(@model, unwrapped)
|
27
28
|
in {
|
28
29
|
event: "message_start" | "message_delta" | "message_stop" | "content_block_start" | "content_block_delta" | "content_block_stop",
|
29
30
|
data: String => data
|
30
31
|
}
|
31
32
|
decoded = JSON.parse(data, symbolize_names: true)
|
32
|
-
|
33
|
+
unwrapped = Anthropic::Internal::Util.dig(decoded, @unwrap)
|
34
|
+
y << Anthropic::Internal::Type::Converter.coerce(@model, unwrapped)
|
33
35
|
in {event: "ping"}
|
34
36
|
next
|
35
37
|
in {event: "error", data: String => data}
|
@@ -471,6 +471,7 @@ module Anthropic
|
|
471
471
|
self.class.validate!(req)
|
472
472
|
model = req.fetch(:model) { Anthropic::Internal::Type::Unknown }
|
473
473
|
opts = req[:options].to_h
|
474
|
+
unwrap = req[:unwrap]
|
474
475
|
Anthropic::RequestOptions.validate!(opts)
|
475
476
|
request = build_request(req.except(:options), opts)
|
476
477
|
url = request.fetch(:url)
|
@@ -487,11 +488,18 @@ module Anthropic
|
|
487
488
|
decoded = Anthropic::Internal::Util.decode_content(response, stream: stream)
|
488
489
|
case req
|
489
490
|
in {stream: Class => st}
|
490
|
-
st.new(
|
491
|
+
st.new(
|
492
|
+
model: model,
|
493
|
+
url: url,
|
494
|
+
status: status,
|
495
|
+
response: response,
|
496
|
+
unwrap: unwrap,
|
497
|
+
stream: decoded
|
498
|
+
)
|
491
499
|
in {page: Class => page}
|
492
500
|
page.new(client: self, req: req, headers: response, page_data: decoded)
|
493
501
|
else
|
494
|
-
unwrapped = Anthropic::Internal::Util.dig(decoded,
|
502
|
+
unwrapped = Anthropic::Internal::Util.dig(decoded, unwrap)
|
495
503
|
Anthropic::Internal::Type::Converter.coerce(model, unwrapped)
|
496
504
|
end
|
497
505
|
end
|
@@ -62,10 +62,14 @@ module Anthropic
|
|
62
62
|
#
|
63
63
|
# @param state [Hash{Symbol=>Object}] .
|
64
64
|
#
|
65
|
-
# @option state [Boolean
|
65
|
+
# @option state [Boolean] :translate_names
|
66
|
+
#
|
67
|
+
# @option state [Boolean] :strictness
|
66
68
|
#
|
67
69
|
# @option state [Hash{Symbol=>Object}] :exactness
|
68
70
|
#
|
71
|
+
# @option state [Class<StandardError>] :error
|
72
|
+
#
|
69
73
|
# @option state [Integer] :branched
|
70
74
|
#
|
71
75
|
# @return [Array<Object>, Object]
|
@@ -74,6 +78,7 @@ module Anthropic
|
|
74
78
|
|
75
79
|
unless value.is_a?(Array)
|
76
80
|
exactness[:no] += 1
|
81
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{Array}")
|
77
82
|
return value
|
78
83
|
end
|
79
84
|
|
@@ -60,7 +60,7 @@ module Anthropic
|
|
60
60
|
[Anthropic::Internal::Type::Converter.type_info(type_info), type_info]
|
61
61
|
end
|
62
62
|
|
63
|
-
setter = "#{name_sym}="
|
63
|
+
setter = :"#{name_sym}="
|
64
64
|
api_name = info.fetch(:api_name, name_sym)
|
65
65
|
nilable = info.fetch(:nil?, false)
|
66
66
|
const = if required && !nilable
|
@@ -84,28 +84,61 @@ module Anthropic
|
|
84
84
|
type_fn: type_fn
|
85
85
|
}
|
86
86
|
|
87
|
-
define_method(setter)
|
87
|
+
define_method(setter) do |value|
|
88
|
+
target = type_fn.call
|
89
|
+
state = Anthropic::Internal::Type::Converter.new_coerce_state(translate_names: false)
|
90
|
+
coerced = Anthropic::Internal::Type::Converter.coerce(target, value, state: state)
|
91
|
+
status = @coerced.store(name_sym, state.fetch(:error) || true)
|
92
|
+
stored =
|
93
|
+
case [target, status]
|
94
|
+
in [Anthropic::Internal::Type::Converter | Symbol, true]
|
95
|
+
coerced
|
96
|
+
else
|
97
|
+
value
|
98
|
+
end
|
99
|
+
@data.store(name_sym, stored)
|
100
|
+
end
|
88
101
|
|
102
|
+
# rubocop:disable Style/CaseEquality
|
103
|
+
# rubocop:disable Metrics/BlockLength
|
89
104
|
define_method(name_sym) do
|
90
105
|
target = type_fn.call
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
Anthropic::
|
97
|
-
|
106
|
+
|
107
|
+
case @coerced[name_sym]
|
108
|
+
in true | false if Anthropic::Internal::Type::Converter === target
|
109
|
+
@data.fetch(name_sym)
|
110
|
+
in ::StandardError => e
|
111
|
+
raise Anthropic::Errors::ConversionError.new(
|
112
|
+
on: self.class,
|
113
|
+
method: __method__,
|
114
|
+
target: target,
|
115
|
+
value: @data.fetch(name_sym),
|
116
|
+
cause: e
|
98
117
|
)
|
118
|
+
else
|
119
|
+
Kernel.then do
|
120
|
+
value = @data.fetch(name_sym) { const == Anthropic::Internal::OMIT ? nil : const }
|
121
|
+
state = Anthropic::Internal::Type::Converter.new_coerce_state(translate_names: false)
|
122
|
+
if (nilable || !required) && value.nil?
|
123
|
+
nil
|
124
|
+
else
|
125
|
+
Anthropic::Internal::Type::Converter.coerce(
|
126
|
+
target, value, state: state
|
127
|
+
)
|
128
|
+
end
|
129
|
+
rescue StandardError => e
|
130
|
+
raise Anthropic::Errors::ConversionError.new(
|
131
|
+
on: self.class,
|
132
|
+
method: __method__,
|
133
|
+
target: target,
|
134
|
+
value: value,
|
135
|
+
cause: e
|
136
|
+
)
|
137
|
+
end
|
99
138
|
end
|
100
|
-
rescue StandardError => e
|
101
|
-
cls = self.class.name.split("::").last
|
102
|
-
message = [
|
103
|
-
"Failed to parse #{cls}.#{__method__} from #{value.class} to #{target.inspect}.",
|
104
|
-
"To get the unparsed API response, use #{cls}[#{__method__.inspect}].",
|
105
|
-
"Cause: #{e.message}"
|
106
|
-
].join(" ")
|
107
|
-
raise Anthropic::Errors::ConversionError.new(message)
|
108
139
|
end
|
140
|
+
# rubocop:enable Metrics/BlockLength
|
141
|
+
# rubocop:enable Style/CaseEquality
|
109
142
|
end
|
110
143
|
|
111
144
|
# @api private
|
@@ -205,23 +238,28 @@ module Anthropic
|
|
205
238
|
#
|
206
239
|
# @param state [Hash{Symbol=>Object}] .
|
207
240
|
#
|
208
|
-
# @option state [Boolean
|
241
|
+
# @option state [Boolean] :translate_names
|
242
|
+
#
|
243
|
+
# @option state [Boolean] :strictness
|
209
244
|
#
|
210
245
|
# @option state [Hash{Symbol=>Object}] :exactness
|
211
246
|
#
|
247
|
+
# @option state [Class<StandardError>] :error
|
248
|
+
#
|
212
249
|
# @option state [Integer] :branched
|
213
250
|
#
|
214
251
|
# @return [self, Object]
|
215
252
|
def coerce(value, state:)
|
216
253
|
exactness = state.fetch(:exactness)
|
217
254
|
|
218
|
-
if value.is_a?(self
|
255
|
+
if value.is_a?(self)
|
219
256
|
exactness[:yes] += 1
|
220
257
|
return value
|
221
258
|
end
|
222
259
|
|
223
260
|
unless (val = Anthropic::Internal::Util.coerce_hash(value)).is_a?(Hash)
|
224
261
|
exactness[:no] += 1
|
262
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{Hash}")
|
225
263
|
return value
|
226
264
|
end
|
227
265
|
exactness[:yes] += 1
|
@@ -229,13 +267,15 @@ module Anthropic
|
|
229
267
|
keys = val.keys.to_set
|
230
268
|
instance = new
|
231
269
|
data = instance.to_h
|
270
|
+
status = instance.instance_variable_get(:@coerced)
|
232
271
|
|
233
272
|
# rubocop:disable Metrics/BlockLength
|
234
273
|
fields.each do |name, field|
|
235
274
|
mode, required, target = field.fetch_values(:mode, :required, :type)
|
236
275
|
api_name, nilable, const = field.fetch_values(:api_name, :nilable, :const)
|
276
|
+
src_name = state.fetch(:translate_names) ? api_name : name
|
237
277
|
|
238
|
-
unless val.key?(
|
278
|
+
unless val.key?(src_name)
|
239
279
|
if required && mode != :dump && const == Anthropic::Internal::OMIT
|
240
280
|
exactness[nilable ? :maybe : :no] += 1
|
241
281
|
else
|
@@ -244,9 +284,10 @@ module Anthropic
|
|
244
284
|
next
|
245
285
|
end
|
246
286
|
|
247
|
-
item = val.fetch(
|
248
|
-
keys.delete(
|
287
|
+
item = val.fetch(src_name)
|
288
|
+
keys.delete(src_name)
|
249
289
|
|
290
|
+
state[:error] = nil
|
250
291
|
converted =
|
251
292
|
if item.nil? && (nilable || !required)
|
252
293
|
exactness[nilable ? :yes : :maybe] += 1
|
@@ -260,6 +301,8 @@ module Anthropic
|
|
260
301
|
item
|
261
302
|
end
|
262
303
|
end
|
304
|
+
|
305
|
+
status.store(name, state.fetch(:error) || true)
|
263
306
|
data.store(name, converted)
|
264
307
|
end
|
265
308
|
# rubocop:enable Metrics/BlockLength
|
@@ -434,7 +477,18 @@ module Anthropic
|
|
434
477
|
# Create a new instance of a model.
|
435
478
|
#
|
436
479
|
# @param data [Hash{Symbol=>Object}, self]
|
437
|
-
def initialize(data = {})
|
480
|
+
def initialize(data = {})
|
481
|
+
@data = {}
|
482
|
+
@coerced = {}
|
483
|
+
Anthropic::Internal::Util.coerce_hash!(data).each do
|
484
|
+
if self.class.known_fields.key?(_1)
|
485
|
+
public_send(:"#{_1}=", _2)
|
486
|
+
else
|
487
|
+
@data.store(_1, _2)
|
488
|
+
@coerced.store(_1, false)
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
438
492
|
|
439
493
|
class << self
|
440
494
|
# @api private
|
@@ -64,12 +64,14 @@ module Anthropic
|
|
64
64
|
# @param url [URI::Generic]
|
65
65
|
# @param status [Integer]
|
66
66
|
# @param response [Net::HTTPResponse]
|
67
|
+
# @param unwrap [Symbol, Integer, Array<Symbol, Integer>, Proc]
|
67
68
|
# @param stream [Enumerable<Object>]
|
68
|
-
def initialize(model:, url:, status:, response:, stream:)
|
69
|
+
def initialize(model:, url:, status:, response:, unwrap:, stream:)
|
69
70
|
@model = model
|
70
71
|
@url = url
|
71
72
|
@status = status
|
72
73
|
@response = response
|
74
|
+
@unwrap = unwrap
|
73
75
|
@stream = stream
|
74
76
|
@iterator = iterator
|
75
77
|
|
@@ -31,14 +31,20 @@ module Anthropic
|
|
31
31
|
class << self
|
32
32
|
# @api private
|
33
33
|
#
|
34
|
+
# Coerce value to Boolean if possible, otherwise return the original value.
|
35
|
+
#
|
34
36
|
# @param value [Boolean, Object]
|
35
37
|
#
|
36
38
|
# @param state [Hash{Symbol=>Object}] .
|
37
39
|
#
|
38
|
-
# @option state [Boolean
|
40
|
+
# @option state [Boolean] :translate_names
|
41
|
+
#
|
42
|
+
# @option state [Boolean] :strictness
|
39
43
|
#
|
40
44
|
# @option state [Hash{Symbol=>Object}] :exactness
|
41
45
|
#
|
46
|
+
# @option state [Class<StandardError>] :error
|
47
|
+
#
|
42
48
|
# @option state [Integer] :branched
|
43
49
|
#
|
44
50
|
# @return [Boolean, Object]
|
@@ -15,10 +15,14 @@ module Anthropic
|
|
15
15
|
#
|
16
16
|
# @param state [Hash{Symbol=>Object}] .
|
17
17
|
#
|
18
|
-
# @option state [Boolean
|
18
|
+
# @option state [Boolean] :translate_names
|
19
|
+
#
|
20
|
+
# @option state [Boolean] :strictness
|
19
21
|
#
|
20
22
|
# @option state [Hash{Symbol=>Object}] :exactness
|
21
23
|
#
|
24
|
+
# @option state [Class<StandardError>] :error
|
25
|
+
#
|
22
26
|
# @option state [Integer] :branched
|
23
27
|
#
|
24
28
|
# @return [Object]
|
@@ -94,6 +98,21 @@ module Anthropic
|
|
94
98
|
end
|
95
99
|
end
|
96
100
|
|
101
|
+
# @api private
|
102
|
+
#
|
103
|
+
# @param translate_names [Boolean]
|
104
|
+
#
|
105
|
+
# @return [Hash{Symbol=>Object}]
|
106
|
+
def new_coerce_state(translate_names: true)
|
107
|
+
{
|
108
|
+
translate_names: translate_names,
|
109
|
+
strictness: true,
|
110
|
+
exactness: {yes: 0, no: 0, maybe: 0},
|
111
|
+
error: nil,
|
112
|
+
branched: 0
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
97
116
|
# @api private
|
98
117
|
#
|
99
118
|
# Based on `target`, transform `value` into `target`, to the extent possible:
|
@@ -110,14 +129,11 @@ module Anthropic
|
|
110
129
|
#
|
111
130
|
# @param value [Object]
|
112
131
|
#
|
113
|
-
# @param state [Hash{Symbol=>Object}] The `strictness` is one of `true`, `false
|
114
|
-
#
|
115
|
-
# targets:
|
132
|
+
# @param state [Hash{Symbol=>Object}] The `strictness` is one of `true`, `false`. This informs the coercion strategy
|
133
|
+
# when we have to decide between multiple possible conversion targets:
|
116
134
|
#
|
117
135
|
# - `true`: the conversion must be exact, with minimum coercion.
|
118
136
|
# - `false`: the conversion can be approximate, with some coercion.
|
119
|
-
# - `:strong`: the conversion must be exact, with no coercion, and raise an error
|
120
|
-
# if not possible.
|
121
137
|
#
|
122
138
|
# The `exactness` is `Hash` with keys being one of `yes`, `no`, or `maybe`. For
|
123
139
|
# any given conversion attempt, the exactness will be updated based on how closely
|
@@ -130,21 +146,20 @@ module Anthropic
|
|
130
146
|
#
|
131
147
|
# See implementation below for more details.
|
132
148
|
#
|
133
|
-
# @option state [Boolean
|
149
|
+
# @option state [Boolean] :translate_names
|
150
|
+
#
|
151
|
+
# @option state [Boolean] :strictness
|
134
152
|
#
|
135
153
|
# @option state [Hash{Symbol=>Object}] :exactness
|
136
154
|
#
|
155
|
+
# @option state [Class<StandardError>] :error
|
156
|
+
#
|
137
157
|
# @option state [Integer] :branched
|
138
158
|
#
|
139
159
|
# @return [Object]
|
140
|
-
def coerce(
|
141
|
-
target,
|
142
|
-
value,
|
143
|
-
state: {strictness: true, exactness: {yes: 0, no: 0, maybe: 0}, branched: 0}
|
144
|
-
)
|
145
|
-
# rubocop:disable Lint/SuppressedException
|
160
|
+
def coerce(target, value, state: Anthropic::Internal::Type::Converter.new_coerce_state)
|
146
161
|
# rubocop:disable Metrics/BlockNesting
|
147
|
-
|
162
|
+
exactness = state.fetch(:exactness)
|
148
163
|
|
149
164
|
case target
|
150
165
|
in Anthropic::Internal::Type::Converter
|
@@ -160,29 +175,26 @@ module Anthropic
|
|
160
175
|
exactness[value.nil? ? :yes : :maybe] += 1
|
161
176
|
return nil
|
162
177
|
in -> { _1 <= Integer }
|
163
|
-
|
178
|
+
case value
|
179
|
+
in Integer
|
164
180
|
exactness[:yes] += 1
|
165
181
|
return value
|
166
|
-
elsif strictness == :strong && Integer(value, exception: false) != value
|
167
|
-
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
168
|
-
raise value.is_a?(Numeric) ? ArgumentError.new(message) : TypeError.new(message)
|
169
182
|
else
|
170
183
|
Kernel.then do
|
171
184
|
return Integer(value).tap { exactness[:maybe] += 1 }
|
172
|
-
rescue ArgumentError, TypeError
|
185
|
+
rescue ArgumentError, TypeError => e
|
186
|
+
state[:error] = e
|
173
187
|
end
|
174
188
|
end
|
175
189
|
in -> { _1 <= Float }
|
176
190
|
if value.is_a?(Numeric)
|
177
191
|
exactness[:yes] += 1
|
178
192
|
return Float(value)
|
179
|
-
elsif strictness == :strong
|
180
|
-
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
181
|
-
raise TypeError.new(message)
|
182
193
|
else
|
183
194
|
Kernel.then do
|
184
195
|
return Float(value).tap { exactness[:maybe] += 1 }
|
185
|
-
rescue ArgumentError, TypeError
|
196
|
+
rescue ArgumentError, TypeError => e
|
197
|
+
state[:error] = e
|
186
198
|
end
|
187
199
|
end
|
188
200
|
in -> { _1 <= String }
|
@@ -194,16 +206,13 @@ module Anthropic
|
|
194
206
|
exactness[:yes] += 1
|
195
207
|
return value.string
|
196
208
|
else
|
197
|
-
|
198
|
-
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
199
|
-
raise TypeError.new(message)
|
200
|
-
end
|
209
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{String}")
|
201
210
|
end
|
202
211
|
in -> { _1 <= Date || _1 <= Time }
|
203
212
|
Kernel.then do
|
204
213
|
return target.parse(value).tap { exactness[:yes] += 1 }
|
205
214
|
rescue ArgumentError, TypeError => e
|
206
|
-
|
215
|
+
state[:error] = e
|
207
216
|
end
|
208
217
|
in -> { _1 <= StringIO } if value.is_a?(String)
|
209
218
|
exactness[:yes] += 1
|
@@ -221,10 +230,8 @@ module Anthropic
|
|
221
230
|
return value
|
222
231
|
end
|
223
232
|
else
|
224
|
-
|
225
|
-
|
226
|
-
raise ArgumentError.new(message)
|
227
|
-
end
|
233
|
+
message = "cannot convert non-matching #{value.class} into #{target.inspect}"
|
234
|
+
state[:error] = ArgumentError.new(message)
|
228
235
|
end
|
229
236
|
else
|
230
237
|
end
|
@@ -232,7 +239,6 @@ module Anthropic
|
|
232
239
|
exactness[:no] += 1
|
233
240
|
value
|
234
241
|
# rubocop:enable Metrics/BlockNesting
|
235
|
-
# rubocop:enable Lint/SuppressedException
|
236
242
|
end
|
237
243
|
|
238
244
|
# @api private
|
@@ -277,8 +283,10 @@ module Anthropic
|
|
277
283
|
define_sorbet_constant!(:CoerceState) do
|
278
284
|
T.type_alias do
|
279
285
|
{
|
280
|
-
|
286
|
+
translate_names: T::Boolean,
|
287
|
+
strictness: T::Boolean,
|
281
288
|
exactness: {yes: Integer, no: Integer, maybe: Integer},
|
289
|
+
error: T::Class[StandardError],
|
282
290
|
branched: Integer
|
283
291
|
}
|
284
292
|
end
|
@@ -81,10 +81,14 @@ module Anthropic
|
|
81
81
|
#
|
82
82
|
# @param state [Hash{Symbol=>Object}] .
|
83
83
|
#
|
84
|
-
# @option state [Boolean
|
84
|
+
# @option state [Boolean] :translate_names
|
85
|
+
#
|
86
|
+
# @option state [Boolean] :strictness
|
85
87
|
#
|
86
88
|
# @option state [Hash{Symbol=>Object}] :exactness
|
87
89
|
#
|
90
|
+
# @option state [Class<StandardError>] :error
|
91
|
+
#
|
88
92
|
# @option state [Integer] :branched
|
89
93
|
#
|
90
94
|
# @return [Symbol, Object]
|
@@ -95,8 +99,12 @@ module Anthropic
|
|
95
99
|
if values.include?(val)
|
96
100
|
exactness[:yes] += 1
|
97
101
|
val
|
102
|
+
elsif values.first&.class == val.class
|
103
|
+
exactness[:maybe] += 1
|
104
|
+
value
|
98
105
|
else
|
99
|
-
exactness[
|
106
|
+
exactness[:no] += 1
|
107
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{self}")
|
100
108
|
value
|
101
109
|
end
|
102
110
|
end
|
@@ -116,11 +124,14 @@ module Anthropic
|
|
116
124
|
#
|
117
125
|
# @return [Object]
|
118
126
|
def to_sorbet_type
|
119
|
-
|
127
|
+
types = values.map { Anthropic::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(_1) }.uniq
|
128
|
+
case types
|
120
129
|
in []
|
121
130
|
T.noreturn
|
122
|
-
in [
|
123
|
-
|
131
|
+
in [type]
|
132
|
+
type
|
133
|
+
else
|
134
|
+
T.any(*types)
|
124
135
|
end
|
125
136
|
end
|
126
137
|
|
@@ -45,10 +45,14 @@ module Anthropic
|
|
45
45
|
#
|
46
46
|
# @param state [Hash{Symbol=>Object}] .
|
47
47
|
#
|
48
|
-
# @option state [Boolean
|
48
|
+
# @option state [Boolean] :translate_names
|
49
|
+
#
|
50
|
+
# @option state [Boolean] :strictness
|
49
51
|
#
|
50
52
|
# @option state [Hash{Symbol=>Object}] :exactness
|
51
53
|
#
|
54
|
+
# @option state [Class<StandardError>] :error
|
55
|
+
#
|
52
56
|
# @option state [Integer] :branched
|
53
57
|
#
|
54
58
|
# @return [StringIO, Object]
|
@@ -62,6 +66,7 @@ module Anthropic
|
|
62
66
|
exactness[:yes] += 1
|
63
67
|
value
|
64
68
|
else
|
69
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{StringIO}")
|
65
70
|
exactness[:no] += 1
|
66
71
|
value
|
67
72
|
end
|
@@ -77,10 +77,14 @@ module Anthropic
|
|
77
77
|
#
|
78
78
|
# @param state [Hash{Symbol=>Object}] .
|
79
79
|
#
|
80
|
-
# @option state [Boolean
|
80
|
+
# @option state [Boolean] :translate_names
|
81
|
+
#
|
82
|
+
# @option state [Boolean] :strictness
|
81
83
|
#
|
82
84
|
# @option state [Hash{Symbol=>Object}] :exactness
|
83
85
|
#
|
86
|
+
# @option state [Class<StandardError>] :error
|
87
|
+
#
|
84
88
|
# @option state [Integer] :branched
|
85
89
|
#
|
86
90
|
# @return [Hash{Symbol=>Object}, Object]
|
@@ -89,6 +93,7 @@ module Anthropic
|
|
89
93
|
|
90
94
|
unless value.is_a?(Hash)
|
91
95
|
exactness[:no] += 1
|
96
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{Hash}")
|
92
97
|
return value
|
93
98
|
end
|
94
99
|
|
@@ -140,14 +140,23 @@ module Anthropic
|
|
140
140
|
|
141
141
|
# @api private
|
142
142
|
#
|
143
|
+
# Tries to efficiently coerce the given value to one of the known variants.
|
144
|
+
#
|
145
|
+
# If the value cannot match any of the known variants, the coercion is considered
|
146
|
+
# non-viable and returns the original value.
|
147
|
+
#
|
143
148
|
# @param value [Object]
|
144
149
|
#
|
145
150
|
# @param state [Hash{Symbol=>Object}] .
|
146
151
|
#
|
147
|
-
# @option state [Boolean
|
152
|
+
# @option state [Boolean] :translate_names
|
153
|
+
#
|
154
|
+
# @option state [Boolean] :strictness
|
148
155
|
#
|
149
156
|
# @option state [Hash{Symbol=>Object}] :exactness
|
150
157
|
#
|
158
|
+
# @option state [Class<StandardError>] :error
|
159
|
+
#
|
151
160
|
# @option state [Integer] :branched
|
152
161
|
#
|
153
162
|
# @return [Object]
|
@@ -158,7 +167,6 @@ module Anthropic
|
|
158
167
|
|
159
168
|
strictness = state.fetch(:strictness)
|
160
169
|
exactness = state.fetch(:exactness)
|
161
|
-
state[:strictness] = strictness == :strong ? true : strictness
|
162
170
|
|
163
171
|
alternatives = []
|
164
172
|
known_variants.each do |_, variant_fn|
|
@@ -177,13 +185,10 @@ module Anthropic
|
|
177
185
|
end
|
178
186
|
end
|
179
187
|
|
180
|
-
case alternatives.sort_by(&:first)
|
188
|
+
case alternatives.sort_by!(&:first)
|
181
189
|
in []
|
182
190
|
exactness[:no] += 1
|
183
|
-
|
184
|
-
message = "no possible conversion of #{value.class} into a variant of #{target.inspect}"
|
185
|
-
raise ArgumentError.new(message)
|
186
|
-
end
|
191
|
+
state[:error] = ArgumentError.new("no matching variant for #{value.inspect}")
|
187
192
|
value
|
188
193
|
in [[_, exact, coerced], *]
|
189
194
|
exact.each { exactness[_1] += _2 }
|
@@ -220,11 +225,14 @@ module Anthropic
|
|
220
225
|
#
|
221
226
|
# @return [Object]
|
222
227
|
def to_sorbet_type
|
223
|
-
|
228
|
+
types = variants.map { Anthropic::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(_1) }.uniq
|
229
|
+
case types
|
224
230
|
in []
|
225
231
|
T.noreturn
|
232
|
+
in [type]
|
233
|
+
type
|
226
234
|
else
|
227
|
-
T.any(*
|
235
|
+
T.any(*types)
|
228
236
|
end
|
229
237
|
end
|
230
238
|
|
@@ -33,14 +33,20 @@ module Anthropic
|
|
33
33
|
class << self
|
34
34
|
# @api private
|
35
35
|
#
|
36
|
+
# No coercion needed for Unknown type.
|
37
|
+
#
|
36
38
|
# @param value [Object]
|
37
39
|
#
|
38
40
|
# @param state [Hash{Symbol=>Object}] .
|
39
41
|
#
|
40
|
-
# @option state [Boolean
|
42
|
+
# @option state [Boolean] :translate_names
|
43
|
+
#
|
44
|
+
# @option state [Boolean] :strictness
|
41
45
|
#
|
42
46
|
# @option state [Hash{Symbol=>Object}] :exactness
|
43
47
|
#
|
48
|
+
# @option state [Class<StandardError>] :error
|
49
|
+
#
|
44
50
|
# @option state [Integer] :branched
|
45
51
|
#
|
46
52
|
# @return [Object]
|