anthropic 1.13.0 → 1.14.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 +19 -0
- data/README.md +31 -1
- data/lib/anthropic/helpers/input_schema/base_model.rb +6 -3
- data/lib/anthropic/helpers/input_schema/json_schema_converter.rb +9 -3
- data/lib/anthropic/helpers/input_schema/supported_schemas.rb +106 -0
- data/lib/anthropic/helpers/input_schema/union_of.rb +3 -1
- data/lib/anthropic/helpers/messages.rb +107 -0
- data/lib/anthropic/helpers/streaming/message_stream.rb +54 -43
- data/lib/anthropic/helpers/tools/base_tool.rb +82 -0
- data/lib/anthropic/helpers/tools/runner.rb +156 -0
- data/lib/anthropic/helpers/tools.rb +5 -0
- data/lib/anthropic/internal/transport/base_client.rb +7 -1
- data/lib/anthropic/internal/transport/pooled_net_requester.rb +6 -2
- data/lib/anthropic/models/beta/beta_tool_use_block.rb +14 -0
- data/lib/anthropic/models/tool_use_block.rb +6 -6
- data/lib/anthropic/resources/beta/messages.rb +23 -5
- data/lib/anthropic/resources/messages.rb +7 -81
- data/lib/anthropic/version.rb +1 -1
- data/lib/anthropic.rb +15 -10
- data/manifest.yaml +1 -0
- data/rbi/anthropic/helpers/input_schema/base_model.rbi +7 -2
- data/rbi/anthropic/helpers/tools/base_tool.rbi +51 -0
- data/rbi/anthropic/helpers/tools/runner.rbi +40 -0
- data/rbi/anthropic/helpers/tools.rbi +5 -0
- data/rbi/anthropic/internal/transport/base_client.rbi +5 -0
- data/rbi/anthropic/internal/transport/pooled_net_requester.rbi +6 -2
- data/rbi/anthropic/internal/type/base_model.rbi +8 -4
- data/rbi/anthropic/models/tool_use_block.rbi +3 -0
- data/rbi/anthropic/resources/beta/messages.rbi +296 -0
- data/sig/anthropic/internal/transport/base_client.rbs +2 -0
- data/sig/anthropic/internal/transport/pooled_net_requester.rbs +4 -1
- metadata +11 -4
- data/lib/anthropic/helpers/input_schema/property_mapping.rb +0 -47
- /data/rbi/anthropic/helpers/{structured_output.rbi → input_schema.rbi} +0 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Anthropic
|
|
4
|
+
module Helpers
|
|
5
|
+
module Tools
|
|
6
|
+
# @api private
|
|
7
|
+
#
|
|
8
|
+
class Runner
|
|
9
|
+
# @return [Anthropic::Models::Beta::MessageCreateParams]
|
|
10
|
+
attr_accessor :params
|
|
11
|
+
|
|
12
|
+
# @return [Boolean]
|
|
13
|
+
def finished? = @finished
|
|
14
|
+
|
|
15
|
+
# @param params [Array<Anthropic::Beta::BetaMessageParam>]
|
|
16
|
+
def feed_messages(*messages)
|
|
17
|
+
self.params = {**params.to_h, messages: params[:messages].to_a + messages}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [Array<Anthropic::Beta::BetaMessageParam>]
|
|
21
|
+
private def current_messages = params&.[](:messages).to_a
|
|
22
|
+
|
|
23
|
+
# @return [Anthropic::Models::BetaMessage, nil]
|
|
24
|
+
def next_message
|
|
25
|
+
message = nil
|
|
26
|
+
unless finished?
|
|
27
|
+
fold do
|
|
28
|
+
message = @client.beta.messages.create(_1)
|
|
29
|
+
[true, message]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
message
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @return [Array<Anthropic::Models::BetaMessage>]
|
|
36
|
+
def run_until_finished
|
|
37
|
+
messages = []
|
|
38
|
+
each_streaming { messages << _1.accumulated_message }
|
|
39
|
+
messages
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @yieldparam [Anthropic::Models::BetaMessage]
|
|
43
|
+
def each_message(&blk)
|
|
44
|
+
unless block_given?
|
|
45
|
+
raise ArgumentError.new("A block must be given to ##{__method__}")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
fold do
|
|
49
|
+
message = @client.beta.messages.create(_1)
|
|
50
|
+
blk.call(message)
|
|
51
|
+
[false, message]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @yieldparam [Anthropic::Internal::Stream<Anthropic::Models::Beta::BetaRawMessageStartEvent, Anthropic::Models::Beta::BetaRawMessageDeltaEvent, Anthropic::Models::Beta::BetaRawMessageStopEvent, Anthropic::Models::Beta::BetaRawContentBlockStartEvent, Anthropic::Models::Beta::BetaRawContentBlockDeltaEvent, Anthropic::Models::Beta::BetaRawContentBlockStopEvent>]
|
|
56
|
+
def each_streaming(&blk)
|
|
57
|
+
unless block_given?
|
|
58
|
+
raise ArgumentError.new("A block must be given to ##{__method__}")
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
fold do
|
|
62
|
+
stream = @client.beta.messages.stream(_1)
|
|
63
|
+
blk.call(stream)
|
|
64
|
+
[false, stream.accumulated_message]
|
|
65
|
+
ensure
|
|
66
|
+
stream&.close
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @api private
|
|
71
|
+
#
|
|
72
|
+
# @yieldparam [Array(Boolean, Anthropic::Models::Beta::MessageCreateParams)]
|
|
73
|
+
private def fold(&blk)
|
|
74
|
+
return nil if finished?
|
|
75
|
+
|
|
76
|
+
count =
|
|
77
|
+
case @param
|
|
78
|
+
in {max_iterations: Integer => m}
|
|
79
|
+
m
|
|
80
|
+
else
|
|
81
|
+
nil
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# rubocop:disable Metrics/BlockLength
|
|
85
|
+
# rubocop:disable Style/CaseEquality
|
|
86
|
+
loop do
|
|
87
|
+
return if (count = count&.pred)&.negative?
|
|
88
|
+
|
|
89
|
+
tools = params[:tools].to_a.grep(Anthropic::Helpers::Tools::BaseTool)
|
|
90
|
+
messages = current_messages
|
|
91
|
+
brk, response = blk.call(params)
|
|
92
|
+
|
|
93
|
+
next unless current_messages.equal?(messages)
|
|
94
|
+
|
|
95
|
+
mapped =
|
|
96
|
+
response
|
|
97
|
+
.content
|
|
98
|
+
.lazy
|
|
99
|
+
.grep(Anthropic::Beta::BetaToolUseBlock)
|
|
100
|
+
.map do |tool_use|
|
|
101
|
+
resp = {type: :tool_result, tool_use_id: tool_use.id}
|
|
102
|
+
if (tool = tools.find { _1.class.model === tool_use.parsed })
|
|
103
|
+
begin
|
|
104
|
+
raw = tool.call(tool_use.parsed)
|
|
105
|
+
is_error = false
|
|
106
|
+
rescue StandardError => e
|
|
107
|
+
is_error = true
|
|
108
|
+
raw = e.message
|
|
109
|
+
end
|
|
110
|
+
else
|
|
111
|
+
is_error = true
|
|
112
|
+
raw = "Error: parsed '#{tool_use.name}' not found"
|
|
113
|
+
end
|
|
114
|
+
content = raw.is_a?(Array) ? raw : raw.to_s
|
|
115
|
+
{**resp, content:, is_error:}
|
|
116
|
+
end
|
|
117
|
+
.to_a
|
|
118
|
+
|
|
119
|
+
if mapped.empty?
|
|
120
|
+
@finished = true
|
|
121
|
+
break
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
content = response.content.map do
|
|
125
|
+
case _1
|
|
126
|
+
in Anthropic::Beta::BetaToolUseBlock
|
|
127
|
+
raw = {**_1, input: _1.parsed}.except(:parsed)
|
|
128
|
+
Anthropic::Internal::Type::Converter.dump(Anthropic::Beta::BetaToolUseBlock, raw)
|
|
129
|
+
else
|
|
130
|
+
_1
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
messages << {role: :assistant, content:}
|
|
135
|
+
messages << {role: :user, content: mapped}
|
|
136
|
+
|
|
137
|
+
break if brk
|
|
138
|
+
end
|
|
139
|
+
# rubocop:enable Style/CaseEquality
|
|
140
|
+
# rubocop:enable Metrics/BlockLength
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# @api private
|
|
144
|
+
#
|
|
145
|
+
# @param client [Anthropic::Client]
|
|
146
|
+
#
|
|
147
|
+
# @param params [Anthropic::Models::Beta::MessageCreateParams]
|
|
148
|
+
def initialize(client, params:)
|
|
149
|
+
@client = client
|
|
150
|
+
@params = params.to_h
|
|
151
|
+
@finished = false
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
@@ -201,7 +201,8 @@ module Anthropic
|
|
|
201
201
|
self.class::PLATFORM_HEADERS,
|
|
202
202
|
{
|
|
203
203
|
"accept" => "application/json",
|
|
204
|
-
"content-type" => "application/json"
|
|
204
|
+
"content-type" => "application/json",
|
|
205
|
+
"user-agent" => user_agent
|
|
205
206
|
},
|
|
206
207
|
headers
|
|
207
208
|
)
|
|
@@ -219,6 +220,11 @@ module Anthropic
|
|
|
219
220
|
# @return [Hash{String=>String}]
|
|
220
221
|
private def auth_headers = {}
|
|
221
222
|
|
|
223
|
+
# @api private
|
|
224
|
+
#
|
|
225
|
+
# @return [String]
|
|
226
|
+
private def user_agent = "#{self.class.name}/Ruby #{Anthropic::VERSION}"
|
|
227
|
+
|
|
222
228
|
# @api private
|
|
223
229
|
#
|
|
224
230
|
# @return [String]
|
|
@@ -16,10 +16,11 @@ module Anthropic
|
|
|
16
16
|
class << self
|
|
17
17
|
# @api private
|
|
18
18
|
#
|
|
19
|
+
# @param cert_store [OpenSSL::X509::Store]
|
|
19
20
|
# @param url [URI::Generic]
|
|
20
21
|
#
|
|
21
22
|
# @return [Net::HTTP]
|
|
22
|
-
def connect(url)
|
|
23
|
+
def connect(cert_store:, url:)
|
|
23
24
|
port =
|
|
24
25
|
case [url.port, url.scheme]
|
|
25
26
|
in [Integer, _]
|
|
@@ -33,6 +34,8 @@ module Anthropic
|
|
|
33
34
|
Net::HTTP.new(url.host, port).tap do
|
|
34
35
|
_1.use_ssl = %w[https wss].include?(url.scheme)
|
|
35
36
|
_1.max_retries = 0
|
|
37
|
+
|
|
38
|
+
(_1.cert_store = cert_store) if _1.use_ssl?
|
|
36
39
|
end
|
|
37
40
|
end
|
|
38
41
|
|
|
@@ -102,7 +105,7 @@ module Anthropic
|
|
|
102
105
|
pool =
|
|
103
106
|
@mutex.synchronize do
|
|
104
107
|
@pools[origin] ||= ConnectionPool.new(size: @size) do
|
|
105
|
-
self.class.connect(url)
|
|
108
|
+
self.class.connect(cert_store: @cert_store, url: url)
|
|
106
109
|
end
|
|
107
110
|
end
|
|
108
111
|
|
|
@@ -192,6 +195,7 @@ module Anthropic
|
|
|
192
195
|
def initialize(size: self.class::DEFAULT_MAX_CONNECTIONS)
|
|
193
196
|
@mutex = Mutex.new
|
|
194
197
|
@size = size
|
|
198
|
+
@cert_store = OpenSSL::X509::Store.new.tap(&:set_default_paths)
|
|
195
199
|
@pools = {}
|
|
196
200
|
end
|
|
197
201
|
|
|
@@ -24,6 +24,20 @@ module Anthropic
|
|
|
24
24
|
# @return [Symbol, :tool_use]
|
|
25
25
|
required :type, const: :tool_use
|
|
26
26
|
|
|
27
|
+
response_only do
|
|
28
|
+
# @api public
|
|
29
|
+
#
|
|
30
|
+
# Parsed input data coerced to the tool's input schema model.
|
|
31
|
+
# Only present when tools are defined using the InputSchema DSL.
|
|
32
|
+
required :parsed, Anthropic::Internal::Type::Unknown
|
|
33
|
+
|
|
34
|
+
# @api private
|
|
35
|
+
#
|
|
36
|
+
# Internal buffer for accumulating partial JSON during streaming.
|
|
37
|
+
# Used by streaming helpers to reconstruct complete JSON input from deltas.
|
|
38
|
+
optional :_json_buf, String
|
|
39
|
+
end
|
|
40
|
+
|
|
27
41
|
# @!method initialize(id:, input:, name:, type: :tool_use)
|
|
28
42
|
# @param id [String]
|
|
29
43
|
# @param input [Object]
|
|
@@ -23,18 +23,18 @@ module Anthropic
|
|
|
23
23
|
# @return [Symbol, :tool_use]
|
|
24
24
|
required :type, const: :tool_use
|
|
25
25
|
|
|
26
|
-
# @api private
|
|
27
|
-
#
|
|
28
|
-
# Internal buffer for accumulating partial JSON during streaming.
|
|
29
|
-
# Used by streaming helpers to reconstruct complete JSON input from deltas.
|
|
30
|
-
optional :json_buf, String
|
|
31
|
-
|
|
32
26
|
response_only do
|
|
33
27
|
# @api public
|
|
34
28
|
#
|
|
35
29
|
# Parsed input data coerced to the tool's input schema model.
|
|
36
30
|
# Only present when tools are defined using the InputSchema DSL.
|
|
37
31
|
optional :parsed, Anthropic::Internal::Type::Unknown
|
|
32
|
+
|
|
33
|
+
# @api private
|
|
34
|
+
#
|
|
35
|
+
# Internal buffer for accumulating partial JSON during streaming.
|
|
36
|
+
# Used by streaming helpers to reconstruct complete JSON input from deltas.
|
|
37
|
+
optional :_json_buf, String
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
# @!method initialize(id:, input:, name:, type: :tool_use)
|
|
@@ -7,6 +7,13 @@ module Anthropic
|
|
|
7
7
|
# @return [Anthropic::Resources::Beta::Messages::Batches]
|
|
8
8
|
attr_reader :batches
|
|
9
9
|
|
|
10
|
+
# @param params [Anthropic::Models::Beta::MessageCreateParams]
|
|
11
|
+
#
|
|
12
|
+
# @return [Anthropic::Helpers::Tools::Runner]
|
|
13
|
+
def tool_runner(params)
|
|
14
|
+
Anthropic::Helpers::Tools::Runner.new(@client, params:)
|
|
15
|
+
end
|
|
16
|
+
|
|
10
17
|
# See {Anthropic::Resources::Beta::Messages#stream_raw} for streaming counterpart.
|
|
11
18
|
#
|
|
12
19
|
# Some parameter documentations has been truncated, see
|
|
@@ -68,8 +75,12 @@ module Anthropic
|
|
|
68
75
|
raise ArgumentError.new(message)
|
|
69
76
|
end
|
|
70
77
|
|
|
78
|
+
tools, models = Anthropic::Helpers::Messages.distill_input_schema_models!(parsed, strict: nil)
|
|
79
|
+
|
|
80
|
+
unwrap = ->(raw) { Anthropic::Helpers::Messages.parse_input_schemas!(raw, tools:, models:) }
|
|
81
|
+
|
|
71
82
|
if options.empty? && @client.timeout == Anthropic::Client::DEFAULT_TIMEOUT_IN_SECONDS
|
|
72
|
-
model = parsed[:model]
|
|
83
|
+
model = parsed[:model]&.to_sym
|
|
73
84
|
max_tokens = parsed[:max_tokens].to_i
|
|
74
85
|
timeout = @client.calculate_nonstreaming_timeout(
|
|
75
86
|
max_tokens,
|
|
@@ -87,6 +98,7 @@ module Anthropic
|
|
|
87
98
|
headers: parsed.slice(*header_params.keys).transform_keys(header_params),
|
|
88
99
|
body: parsed.except(*header_params.keys),
|
|
89
100
|
model: Anthropic::Beta::BetaMessage,
|
|
101
|
+
unwrap: unwrap,
|
|
90
102
|
options: options
|
|
91
103
|
)
|
|
92
104
|
end
|
|
@@ -152,16 +164,22 @@ module Anthropic
|
|
|
152
164
|
raise ArgumentError.new(message)
|
|
153
165
|
end
|
|
154
166
|
parsed.store(:stream, true)
|
|
167
|
+
tools, models = Anthropic::Helpers::Messages.distill_input_schema_models!(parsed, strict: nil)
|
|
168
|
+
|
|
169
|
+
header_params = {betas: "anthropic-beta"}
|
|
155
170
|
raw_stream = @client.request(
|
|
156
171
|
method: :post,
|
|
157
172
|
path: "v1/messages?beta=true",
|
|
158
|
-
headers: {
|
|
159
|
-
|
|
173
|
+
headers: {
|
|
174
|
+
"accept" => "text/event-stream",
|
|
175
|
+
**parsed.slice(*header_params.keys)
|
|
176
|
+
}.transform_keys(header_params),
|
|
177
|
+
body: parsed.except(*header_params.keys),
|
|
160
178
|
stream: Anthropic::Internal::Stream,
|
|
161
179
|
model: Anthropic::Beta::BetaRawMessageStreamEvent,
|
|
162
|
-
options: options
|
|
180
|
+
options: {timeout: 600, **options}
|
|
163
181
|
)
|
|
164
|
-
Anthropic::Streaming::MessageStream.new(raw_stream:
|
|
182
|
+
Anthropic::Streaming::MessageStream.new(raw_stream:, tools:, models:)
|
|
165
183
|
end
|
|
166
184
|
|
|
167
185
|
# See {Anthropic::Resources::Beta::Messages#create} for non-streaming counterpart.
|
|
@@ -59,14 +59,12 @@ module Anthropic
|
|
|
59
59
|
raise ArgumentError.new(message)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
tools, models = Anthropic::Helpers::Messages.distill_input_schema_models!(parsed, strict: nil)
|
|
63
63
|
|
|
64
|
-
unwrap =
|
|
65
|
-
->(raw) { parse_structured_outputs!(raw, tool_models) }
|
|
66
|
-
end
|
|
64
|
+
unwrap = ->(raw) { Anthropic::Helpers::Messages.parse_input_schemas!(raw, tools:, models:) }
|
|
67
65
|
|
|
68
66
|
if options.empty? && @client.timeout == Anthropic::Client::DEFAULT_TIMEOUT_IN_SECONDS
|
|
69
|
-
model = parsed[:model]
|
|
67
|
+
model = parsed[:model]&.to_sym
|
|
70
68
|
max_tokens = parsed[:max_tokens].to_i
|
|
71
69
|
timeout = @client.calculate_nonstreaming_timeout(
|
|
72
70
|
max_tokens,
|
|
@@ -87,6 +85,8 @@ module Anthropic
|
|
|
87
85
|
)
|
|
88
86
|
end
|
|
89
87
|
|
|
88
|
+
alias_method :parse, :create
|
|
89
|
+
|
|
90
90
|
# See {Anthropic::Resources::Messages#create} for non-streaming counterpart.
|
|
91
91
|
#
|
|
92
92
|
# Some parameter documentations has been truncated, see
|
|
@@ -141,7 +141,7 @@ module Anthropic
|
|
|
141
141
|
end
|
|
142
142
|
parsed.store(:stream, true)
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
tools, models = Anthropic::Helpers::Messages.distill_input_schema_models!(parsed, strict: nil)
|
|
145
145
|
|
|
146
146
|
raw_stream = @client.request(
|
|
147
147
|
method: :post,
|
|
@@ -152,10 +152,7 @@ module Anthropic
|
|
|
152
152
|
model: Anthropic::Models::RawMessageStreamEvent,
|
|
153
153
|
options: options
|
|
154
154
|
)
|
|
155
|
-
Anthropic::Streaming::MessageStream.new(
|
|
156
|
-
raw_stream: raw_stream,
|
|
157
|
-
tool_models: tool_models
|
|
158
|
-
)
|
|
155
|
+
Anthropic::Streaming::MessageStream.new(raw_stream:, tools:, models:)
|
|
159
156
|
end
|
|
160
157
|
|
|
161
158
|
# See {Anthropic::Resources::Messages#create} for non-streaming counterpart.
|
|
@@ -270,77 +267,6 @@ module Anthropic
|
|
|
270
267
|
@client = client
|
|
271
268
|
@batches = Anthropic::Resources::Messages::Batches.new(client: client)
|
|
272
269
|
end
|
|
273
|
-
|
|
274
|
-
private
|
|
275
|
-
|
|
276
|
-
# Extract tool models from the request and convert them to JSON Schema
|
|
277
|
-
# Returns a hash mapping tool name to Ruby model.
|
|
278
|
-
def get_structured_output_models(parsed)
|
|
279
|
-
tool_models = {}
|
|
280
|
-
|
|
281
|
-
case parsed
|
|
282
|
-
in {tools: Array => tools}
|
|
283
|
-
mapped = tools.map do |tool|
|
|
284
|
-
case tool
|
|
285
|
-
# Direct tool class:
|
|
286
|
-
in Anthropic::Helpers::InputSchema::JsonSchemaConverter
|
|
287
|
-
name = tool.name.split("::").last
|
|
288
|
-
description = extract_class_description(tool)
|
|
289
|
-
tool_models.store(name, tool)
|
|
290
|
-
{
|
|
291
|
-
name: name,
|
|
292
|
-
description: description,
|
|
293
|
-
input_schema: tool.to_json_schema
|
|
294
|
-
}
|
|
295
|
-
# Tool with explicit name/description and BaseModel as input_schema:
|
|
296
|
-
in {name: String => name,
|
|
297
|
-
input_schema: Anthropic::Helpers::InputSchema::JsonSchemaConverter => model,
|
|
298
|
-
**rest}
|
|
299
|
-
tool_models.store(name, model)
|
|
300
|
-
rest.merge(
|
|
301
|
-
name: name,
|
|
302
|
-
input_schema: model.to_json_schema
|
|
303
|
-
)
|
|
304
|
-
else
|
|
305
|
-
# Any other format (pass through unchanged)
|
|
306
|
-
# This includes raw JSON schemas and any other tool definitions.
|
|
307
|
-
tool
|
|
308
|
-
end
|
|
309
|
-
end
|
|
310
|
-
tools.replace(mapped)
|
|
311
|
-
else
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
tool_models
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
# Extract class description from a BaseModel class
|
|
318
|
-
def extract_class_description(klass)
|
|
319
|
-
klass.respond_to?(:doc_string) ? klass.doc_string : nil
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
def parse_structured_outputs!(raw, tool_models)
|
|
323
|
-
return raw if tool_models.empty?
|
|
324
|
-
|
|
325
|
-
raw[:content]&.each do |content|
|
|
326
|
-
next unless content[:type] == "tool_use"
|
|
327
|
-
|
|
328
|
-
model = tool_models[content[:name]]
|
|
329
|
-
next unless model
|
|
330
|
-
|
|
331
|
-
begin
|
|
332
|
-
parsed_input = content[:input]
|
|
333
|
-
|
|
334
|
-
coerced = Anthropic::Internal::Type::Converter.coerce(model, parsed_input)
|
|
335
|
-
|
|
336
|
-
content.store(:parsed, coerced)
|
|
337
|
-
rescue StandardError => e
|
|
338
|
-
content.store(:parsed, {error: e.message})
|
|
339
|
-
end
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
raw
|
|
343
|
-
end
|
|
344
270
|
end
|
|
345
271
|
end
|
|
346
272
|
end
|
data/lib/anthropic/version.rb
CHANGED
data/lib/anthropic.rb
CHANGED
|
@@ -9,6 +9,7 @@ require "erb"
|
|
|
9
9
|
require "etc"
|
|
10
10
|
require "json"
|
|
11
11
|
require "net/http"
|
|
12
|
+
require "openssl"
|
|
12
13
|
require "pathname"
|
|
13
14
|
require "rbconfig"
|
|
14
15
|
require "securerandom"
|
|
@@ -55,6 +56,17 @@ require_relative "anthropic/helpers/bedrock/client"
|
|
|
55
56
|
require_relative "anthropic/helpers/vertex/client"
|
|
56
57
|
require_relative "anthropic/bedrock"
|
|
57
58
|
require_relative "anthropic/vertex"
|
|
59
|
+
require_relative "anthropic/helpers/input_schema"
|
|
60
|
+
require_relative "anthropic/helpers/input_schema/supported_schemas"
|
|
61
|
+
require_relative "anthropic/helpers/input_schema/json_schema_converter"
|
|
62
|
+
require_relative "anthropic/helpers/input_schema/base_model"
|
|
63
|
+
require_relative "anthropic/helpers/input_schema/array_of"
|
|
64
|
+
require_relative "anthropic/helpers/input_schema/boolean"
|
|
65
|
+
require_relative "anthropic/helpers/input_schema/enum_of"
|
|
66
|
+
require_relative "anthropic/helpers/input_schema/union_of"
|
|
67
|
+
require_relative "anthropic/helpers/input_schema/parsed_json"
|
|
68
|
+
require_relative "anthropic/input_schema"
|
|
69
|
+
require_relative "anthropic/helpers/messages"
|
|
58
70
|
require_relative "anthropic/internal/stream"
|
|
59
71
|
require_relative "anthropic/internal/jsonl_stream"
|
|
60
72
|
require_relative "anthropic/internal/page"
|
|
@@ -412,13 +424,6 @@ require_relative "anthropic/resources/completions"
|
|
|
412
424
|
require_relative "anthropic/resources/messages"
|
|
413
425
|
require_relative "anthropic/resources/messages/batches"
|
|
414
426
|
require_relative "anthropic/resources/models"
|
|
415
|
-
require_relative "anthropic/helpers/
|
|
416
|
-
require_relative "anthropic/helpers/
|
|
417
|
-
require_relative "anthropic/helpers/
|
|
418
|
-
require_relative "anthropic/helpers/input_schema/base_model"
|
|
419
|
-
require_relative "anthropic/helpers/input_schema/array_of"
|
|
420
|
-
require_relative "anthropic/helpers/input_schema/boolean"
|
|
421
|
-
require_relative "anthropic/helpers/input_schema/enum_of"
|
|
422
|
-
require_relative "anthropic/helpers/input_schema/union_of"
|
|
423
|
-
require_relative "anthropic/helpers/input_schema/parsed_json"
|
|
424
|
-
require_relative "anthropic/input_schema"
|
|
427
|
+
require_relative "anthropic/helpers/tools/runner"
|
|
428
|
+
require_relative "anthropic/helpers/tools/base_tool"
|
|
429
|
+
require_relative "anthropic/helpers/tools"
|
data/manifest.yaml
CHANGED
|
@@ -12,8 +12,13 @@ module Anthropic
|
|
|
12
12
|
extend Anthropic::Helpers::InputSchema::JsonSchemaConverter
|
|
13
13
|
|
|
14
14
|
class << self
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
# @api public
|
|
16
|
+
#
|
|
17
|
+
sig { params(description: String).returns(T.class_of(String)) }
|
|
18
|
+
def description(description)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
alias_method :doc, :description
|
|
17
22
|
end
|
|
18
23
|
end
|
|
19
24
|
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
|
|
3
|
+
module Anthropic
|
|
4
|
+
module Helpers
|
|
5
|
+
module Tools
|
|
6
|
+
# @api private
|
|
7
|
+
#
|
|
8
|
+
class BaseTool
|
|
9
|
+
include Anthropic::Internal::Type::Converter
|
|
10
|
+
include Anthropic::Helpers::InputSchema::JsonSchemaConverter
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
# @api public
|
|
14
|
+
#
|
|
15
|
+
sig { returns(T.class_of(Anthropic::Helpers::InputSchema::BaseModel)) }
|
|
16
|
+
attr_reader :model
|
|
17
|
+
|
|
18
|
+
sig { returns(T.class_of(String)) }
|
|
19
|
+
attr_reader :doc_string
|
|
20
|
+
|
|
21
|
+
# @api public
|
|
22
|
+
#
|
|
23
|
+
sig { params(description: String).returns(T.class_of(String)) }
|
|
24
|
+
def description(description)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
alias_method :doc, :description
|
|
28
|
+
|
|
29
|
+
# @api public
|
|
30
|
+
#
|
|
31
|
+
sig { params(model: T.class_of(Anthropic::Helpers::InputSchema::BaseModel)).returns(T.class_of(Anthropic::Helpers::InputSchema::BaseModel)) }
|
|
32
|
+
def input_schema(model) = (@model = model)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @api public
|
|
36
|
+
#
|
|
37
|
+
# Override the `#parse` method to customize the pre-processing of the tool call argument
|
|
38
|
+
#
|
|
39
|
+
sig { params(value: T.anything).returns(T.anything) }
|
|
40
|
+
def parse(value)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @api public
|
|
44
|
+
#
|
|
45
|
+
sig { params(parsed: Anthropic::Helpers::InputSchema::BaseModel).returns(T.anything) }
|
|
46
|
+
def call(parsed)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
|
|
3
|
+
module Anthropic
|
|
4
|
+
module Helpers
|
|
5
|
+
module Tools
|
|
6
|
+
# @api private
|
|
7
|
+
#
|
|
8
|
+
class Runner
|
|
9
|
+
sig { returns(Anthropic::Models::Beta::MessageCreateParams) }
|
|
10
|
+
attr_accessor :params
|
|
11
|
+
|
|
12
|
+
sig { returns(T::Boolean) }
|
|
13
|
+
def finished?; end
|
|
14
|
+
|
|
15
|
+
sig { params(messages: Anthropic::Models::Beta::BetaMessageParam).void }
|
|
16
|
+
def feed_messages(*messages); end
|
|
17
|
+
|
|
18
|
+
sig { returns(Anthropic::Models::BetaMessage) }
|
|
19
|
+
def next_message; end
|
|
20
|
+
|
|
21
|
+
sig { returns(T::Array[Anthropic::Models::BetaMessage]) }
|
|
22
|
+
def run_until_finished; end
|
|
23
|
+
|
|
24
|
+
sig do
|
|
25
|
+
params(
|
|
26
|
+
blk: T.proc.params(arg0: Anthropic::Models::BetaMessage).void
|
|
27
|
+
).void
|
|
28
|
+
end
|
|
29
|
+
def each_message(&blk); end
|
|
30
|
+
|
|
31
|
+
sig do
|
|
32
|
+
params(
|
|
33
|
+
blk: T.proc.params(arg0: Anthropic::Streaming::MessageStream).void
|
|
34
|
+
).void
|
|
35
|
+
end
|
|
36
|
+
def each_streaming(&blk); end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -26,8 +26,12 @@ module Anthropic
|
|
|
26
26
|
|
|
27
27
|
class << self
|
|
28
28
|
# @api private
|
|
29
|
-
sig
|
|
30
|
-
|
|
29
|
+
sig do
|
|
30
|
+
params(cert_store: OpenSSL::X509::Store, url: URI::Generic).returns(
|
|
31
|
+
Net::HTTP
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
def connect(cert_store:, url:)
|
|
31
35
|
end
|
|
32
36
|
|
|
33
37
|
# @api private
|