anthropic 1.7.0 → 1.8.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 +20 -0
- data/README.md +1 -1
- data/lib/anthropic/helpers/input_schema/array_of.rb +41 -0
- data/lib/anthropic/helpers/input_schema/base_model.rb +86 -0
- data/lib/anthropic/helpers/input_schema/boolean.rb +29 -0
- data/lib/anthropic/helpers/input_schema/enum_of.rb +63 -0
- data/lib/anthropic/helpers/input_schema/json_schema_converter.rb +199 -0
- data/lib/anthropic/helpers/input_schema/parsed_json.rb +39 -0
- data/lib/anthropic/helpers/input_schema/property_mapping.rb +47 -0
- data/lib/anthropic/helpers/input_schema/union_of.rb +56 -0
- data/lib/anthropic/helpers/input_schema.rb +16 -0
- data/lib/anthropic/helpers/streaming/message_stream.rb +41 -1
- data/lib/anthropic/input_schema.rb +10 -0
- data/lib/anthropic/internal/stream.rb +2 -1
- data/lib/anthropic/internal/transport/base_client.rb +1 -2
- data/lib/anthropic/internal/transport/pooled_net_requester.rb +1 -9
- data/lib/anthropic/internal/type/base_model.rb +2 -9
- data/lib/anthropic/internal/util.rb +1 -1
- data/lib/anthropic/models/beta/beta_bash_code_execution_output_block.rb +25 -0
- data/lib/anthropic/models/beta/beta_bash_code_execution_output_block_param.rb +25 -0
- data/lib/anthropic/models/beta/beta_bash_code_execution_result_block.rb +44 -0
- data/lib/anthropic/models/beta/beta_bash_code_execution_result_block_param.rb +44 -0
- data/lib/anthropic/models/beta/beta_bash_code_execution_tool_result_block.rb +43 -0
- data/lib/anthropic/models/beta/beta_bash_code_execution_tool_result_block_param.rb +53 -0
- data/lib/anthropic/models/beta/beta_bash_code_execution_tool_result_error.rb +39 -0
- data/lib/anthropic/models/beta/beta_bash_code_execution_tool_result_error_param.rb +39 -0
- data/lib/anthropic/models/beta/beta_code_execution_tool_20250825.rb +40 -0
- data/lib/anthropic/models/beta/beta_content_block.rb +6 -1
- data/lib/anthropic/models/beta/beta_content_block_param.rb +7 -1
- data/lib/anthropic/models/beta/beta_message.rb +2 -2
- data/lib/anthropic/models/beta/beta_message_param.rb +3 -3
- data/lib/anthropic/models/beta/beta_raw_content_block_start_event.rb +8 -3
- data/lib/anthropic/models/beta/beta_server_tool_use_block.rb +2 -0
- data/lib/anthropic/models/beta/beta_server_tool_use_block_param.rb +2 -0
- data/lib/anthropic/models/beta/beta_text_editor_code_execution_create_result_block.rb +25 -0
- data/lib/anthropic/models/beta/beta_text_editor_code_execution_create_result_block_param.rb +26 -0
- data/lib/anthropic/models/beta/beta_text_editor_code_execution_str_replace_result_block.rb +49 -0
- data/lib/anthropic/models/beta/beta_text_editor_code_execution_str_replace_result_block_param.rb +50 -0
- data/lib/anthropic/models/beta/beta_text_editor_code_execution_tool_result_block.rb +47 -0
- data/lib/anthropic/models/beta/beta_text_editor_code_execution_tool_result_block_param.rb +57 -0
- data/lib/anthropic/models/beta/beta_text_editor_code_execution_tool_result_error.rb +45 -0
- data/lib/anthropic/models/beta/beta_text_editor_code_execution_tool_result_error_param.rb +46 -0
- data/lib/anthropic/models/beta/beta_text_editor_code_execution_view_result_block.rb +61 -0
- data/lib/anthropic/models/beta/beta_text_editor_code_execution_view_result_block_param.rb +62 -0
- data/lib/anthropic/models/beta/beta_tool_union.rb +3 -1
- data/lib/anthropic/models/beta/message_count_tokens_params.rb +7 -30
- data/lib/anthropic/models/beta/message_create_params.rb +3 -26
- data/lib/anthropic/models/beta/messages/batch_create_params.rb +6 -36
- data/lib/anthropic/models/beta/messages/beta_message_batch.rb +1 -4
- data/lib/anthropic/models/beta_error_response.rb +7 -1
- data/lib/anthropic/models/error_response.rb +7 -1
- data/lib/anthropic/models/message_count_tokens_params.rb +1 -24
- data/lib/anthropic/models/message_create_params.rb +1 -24
- data/lib/anthropic/models/messages/batch_create_params.rb +2 -28
- data/lib/anthropic/models/tool_use_block.rb +8 -0
- data/lib/anthropic/resources/beta/messages.rb +3 -3
- data/lib/anthropic/resources/messages.rb +85 -1
- data/lib/anthropic/version.rb +1 -1
- data/lib/anthropic.rb +29 -0
- data/rbi/anthropic/errors.rbi +2 -2
- data/rbi/anthropic/helpers/input_schema/array_of.rbi +16 -0
- data/rbi/anthropic/helpers/input_schema/base_model.rbi +21 -0
- data/rbi/anthropic/helpers/input_schema/boolean.rbi +11 -0
- data/rbi/anthropic/helpers/input_schema/enum_of.rbi +30 -0
- data/rbi/anthropic/helpers/input_schema/json_schema_converter.rbi +89 -0
- data/rbi/anthropic/helpers/input_schema/union_of.rbi +23 -0
- data/rbi/anthropic/helpers/structured_output.rbi +16 -0
- data/rbi/anthropic/input_schema.rbi +12 -0
- data/rbi/anthropic/models/beta/beta_bash_code_execution_output_block.rbi +33 -0
- data/rbi/anthropic/models/beta/beta_bash_code_execution_output_block_param.rbi +34 -0
- data/rbi/anthropic/models/beta/beta_bash_code_execution_result_block.rbi +72 -0
- data/rbi/anthropic/models/beta/beta_bash_code_execution_result_block_param.rbi +77 -0
- data/rbi/anthropic/models/beta/beta_bash_code_execution_tool_result_block.rbi +86 -0
- data/rbi/anthropic/models/beta/beta_bash_code_execution_tool_result_block_param.rbi +110 -0
- data/rbi/anthropic/models/beta/beta_bash_code_execution_tool_result_error.rbi +101 -0
- data/rbi/anthropic/models/beta/beta_bash_code_execution_tool_result_error_param.rbi +101 -0
- data/rbi/anthropic/models/beta/beta_code_execution_tool_20250825.rbi +72 -0
- data/rbi/anthropic/models/beta/beta_content_block.rbi +2 -0
- data/rbi/anthropic/models/beta/beta_content_block_param.rbi +2 -0
- data/rbi/anthropic/models/beta/beta_message.rbi +2 -0
- data/rbi/anthropic/models/beta/beta_raw_content_block_start_event.rbi +4 -0
- data/rbi/anthropic/models/beta/beta_server_tool_use_block.rbi +10 -0
- data/rbi/anthropic/models/beta/beta_server_tool_use_block_param.rbi +10 -0
- data/rbi/anthropic/models/beta/beta_text_editor_code_execution_create_result_block.rbi +41 -0
- data/rbi/anthropic/models/beta/beta_text_editor_code_execution_create_result_block_param.rbi +41 -0
- data/rbi/anthropic/models/beta/beta_text_editor_code_execution_str_replace_result_block.rbi +73 -0
- data/rbi/anthropic/models/beta/beta_text_editor_code_execution_str_replace_result_block_param.rbi +73 -0
- data/rbi/anthropic/models/beta/beta_text_editor_code_execution_tool_result_block.rbi +90 -0
- data/rbi/anthropic/models/beta/beta_text_editor_code_execution_tool_result_block_param.rbi +118 -0
- data/rbi/anthropic/models/beta/beta_text_editor_code_execution_tool_result_error.rbi +110 -0
- data/rbi/anthropic/models/beta/beta_text_editor_code_execution_tool_result_error_param.rbi +110 -0
- data/rbi/anthropic/models/beta/beta_text_editor_code_execution_view_result_block.rbi +118 -0
- data/rbi/anthropic/models/beta/beta_text_editor_code_execution_view_result_block_param.rbi +118 -0
- data/rbi/anthropic/models/beta/beta_tool_union.rbi +1 -0
- data/rbi/anthropic/models/beta/message_count_tokens_params.rbi +7 -48
- data/rbi/anthropic/models/beta/message_create_params.rbi +6 -48
- data/rbi/anthropic/models/beta/messages/batch_create_params.rbi +6 -48
- data/rbi/anthropic/models/beta_error_response.rbi +10 -2
- data/rbi/anthropic/models/error_response.rbi +10 -2
- data/rbi/anthropic/models/message_count_tokens_params.rbi +2 -48
- data/rbi/anthropic/models/message_create_params.rbi +2 -48
- data/rbi/anthropic/models/messages/batch_create_params.rbi +2 -48
- data/rbi/anthropic/resources/beta/messages.rbi +6 -72
- data/rbi/anthropic/resources/messages.rbi +3 -72
- data/sig/anthropic/models/beta/beta_bash_code_execution_output_block.rbs +23 -0
- data/sig/anthropic/models/beta/beta_bash_code_execution_output_block_param.rbs +23 -0
- data/sig/anthropic/models/beta/beta_bash_code_execution_result_block.rbs +44 -0
- data/sig/anthropic/models/beta/beta_bash_code_execution_result_block_param.rbs +44 -0
- data/sig/anthropic/models/beta/beta_bash_code_execution_tool_result_block.rbs +44 -0
- data/sig/anthropic/models/beta/beta_bash_code_execution_tool_result_block_param.rbs +49 -0
- data/sig/anthropic/models/beta/beta_bash_code_execution_tool_result_error.rbs +48 -0
- data/sig/anthropic/models/beta/beta_bash_code_execution_tool_result_error_param.rbs +48 -0
- data/sig/anthropic/models/beta/beta_code_execution_tool_20250825.rbs +34 -0
- data/sig/anthropic/models/beta/beta_content_block.rbs +2 -0
- data/sig/anthropic/models/beta/beta_content_block_param.rbs +2 -0
- data/sig/anthropic/models/beta/beta_raw_content_block_start_event.rbs +2 -0
- data/sig/anthropic/models/beta/beta_server_tool_use_block.rbs +7 -1
- data/sig/anthropic/models/beta/beta_server_tool_use_block_param.rbs +7 -1
- data/sig/anthropic/models/beta/beta_text_editor_code_execution_create_result_block.rbs +29 -0
- data/sig/anthropic/models/beta/beta_text_editor_code_execution_create_result_block_param.rbs +29 -0
- data/sig/anthropic/models/beta/beta_text_editor_code_execution_str_replace_result_block.rbs +49 -0
- data/sig/anthropic/models/beta/beta_text_editor_code_execution_str_replace_result_block_param.rbs +49 -0
- data/sig/anthropic/models/beta/beta_text_editor_code_execution_tool_result_block.rbs +46 -0
- data/sig/anthropic/models/beta/beta_text_editor_code_execution_tool_result_block_param.rbs +51 -0
- data/sig/anthropic/models/beta/beta_text_editor_code_execution_tool_result_error.rbs +53 -0
- data/sig/anthropic/models/beta/beta_text_editor_code_execution_tool_result_error_param.rbs +53 -0
- data/sig/anthropic/models/beta/beta_text_editor_code_execution_view_result_block.rbs +61 -0
- data/sig/anthropic/models/beta/beta_text_editor_code_execution_view_result_block_param.rbs +61 -0
- data/sig/anthropic/models/beta/beta_tool_union.rbs +1 -0
- data/sig/anthropic/models/beta/message_count_tokens_params.rbs +1 -0
- data/sig/anthropic/models/beta_error_response.rbs +13 -2
- data/sig/anthropic/models/error_response.rbs +13 -2
- metadata +77 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bffc3e0dc22d67590f26385ec3af28ad569d31d7c7c9ba90245e39122addd1c
|
4
|
+
data.tar.gz: 0f498573a662f41c2adc7a0d01cdd7113a8a27b94f3db60e7f4b03be91abf999
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 106bf53c21f57d53c2fc1aad81be8aa244093c03b246e175de0cab37fc876aa99cd0b2ddf8448460a88201bba57e3893ca0c2c32bc4b65001b9a5aea3e223694
|
7
|
+
data.tar.gz: 3199e41a1e31cdd83142fe37c35a8d016b948106c4416ecf75b475d6c392057c44392b635d3b9d5f88564b6df4ee9e2480d56cf5d407b3d68d91f27e8b5a88c3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.8.0 (2025-09-02)
|
4
|
+
|
5
|
+
Full Changelog: [v1.7.0...v1.8.0](https://github.com/anthropics/anthropic-sdk-ruby/compare/v1.7.0...v1.8.0)
|
6
|
+
|
7
|
+
### Features
|
8
|
+
|
9
|
+
* **client:** adds support for code-execution-2025-08-26 tool ([28e554e](https://github.com/anthropics/anthropic-sdk-ruby/commit/28e554ec75e8c34d20ef1e021672f9a02d5be3ec))
|
10
|
+
* input schemas ([#660](https://github.com/anthropics/anthropic-sdk-ruby/issues/660)) ([3e062c0](https://github.com/anthropics/anthropic-sdk-ruby/commit/3e062c03b0fc964877095a34cb69de9ba63dfa19))
|
11
|
+
|
12
|
+
|
13
|
+
### Bug Fixes
|
14
|
+
|
15
|
+
* bump sorbet version and fix new type errors from the breaking change ([3c4f15d](https://github.com/anthropics/anthropic-sdk-ruby/commit/3c4f15d8f4115d6da6d8589856e7654162f91110))
|
16
|
+
* correctly raise errors encountered during streaming ([be9bc45](https://github.com/anthropics/anthropic-sdk-ruby/commit/be9bc45d96ac227fd5648281199a7c8dd234897d))
|
17
|
+
|
18
|
+
|
19
|
+
### Chores
|
20
|
+
|
21
|
+
* add json schema comment for rubocop.yml ([3fce402](https://github.com/anthropics/anthropic-sdk-ruby/commit/3fce4021da72749b127adacee9436327d4b03f60))
|
22
|
+
|
3
23
|
## 1.7.0 (2025-08-13)
|
4
24
|
|
5
25
|
Full Changelog: [v1.6.0...v1.7.0](https://github.com/anthropics/anthropic-sdk-ruby/compare/v1.6.0...v1.7.0)
|
data/README.md
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anthropic
|
4
|
+
module Helpers
|
5
|
+
module InputSchema
|
6
|
+
# @generic Elem
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# example = Anthropic::ArrayOf[Integer]
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# example = Anthropic::ArrayOf[Integer, nil?: true, doc: "hi there!"]
|
13
|
+
class ArrayOf < Anthropic::Internal::Type::ArrayOf
|
14
|
+
include Anthropic::Helpers::InputSchema::JsonSchemaConverter
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
#
|
18
|
+
# @param state [Hash{Symbol=>Object}]
|
19
|
+
#
|
20
|
+
# @option state [Hash{Object=>String}] :defs
|
21
|
+
#
|
22
|
+
# @option state [Array<String>] :path
|
23
|
+
#
|
24
|
+
# @return [Hash{Symbol=>Object}]
|
25
|
+
def to_json_schema_inner(state:)
|
26
|
+
Anthropic::Helpers::InputSchema::JsonSchemaConverter.cache_def!(state, type: self) do
|
27
|
+
state.fetch(:path) << "[]"
|
28
|
+
items = Anthropic::Helpers::InputSchema::JsonSchemaConverter.to_json_schema_inner(
|
29
|
+
item_type,
|
30
|
+
state: state
|
31
|
+
)
|
32
|
+
items = Anthropic::Helpers::InputSchema::JsonSchemaConverter.to_nilable(items) if nilable?
|
33
|
+
Anthropic::Helpers::InputSchema::JsonSchemaConverter.assoc_meta!(items, meta: @meta)
|
34
|
+
|
35
|
+
{type: "array", items: items}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anthropic
|
4
|
+
module Helpers
|
5
|
+
module InputSchema
|
6
|
+
# Represents a response from Anthropic's API where the model's output has been structured according to a schema predefined by the user.
|
7
|
+
#
|
8
|
+
# This class is specifically used when making requests with the `input_schema` parameter.
|
9
|
+
#
|
10
|
+
# See {examples/input_schemas.rb} for a complete example of use
|
11
|
+
class BaseModel < Anthropic::Internal::Type::BaseModel
|
12
|
+
extend Anthropic::Helpers::InputSchema::JsonSchemaConverter
|
13
|
+
|
14
|
+
class << self
|
15
|
+
# @return [Hash{Symbol=>Object}]
|
16
|
+
def to_json_schema = Anthropic::Helpers::InputSchema::JsonSchemaConverter.to_json_schema(self)
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
# @param state [Hash{Symbol=>Object}]
|
21
|
+
#
|
22
|
+
# @option state [Hash{Object=>String}] :defs
|
23
|
+
#
|
24
|
+
# @option state [Array<String>] :path
|
25
|
+
#
|
26
|
+
# @return [Hash{Symbol=>Object}]
|
27
|
+
def to_json_schema_inner(state:)
|
28
|
+
Anthropic::Helpers::InputSchema::JsonSchemaConverter.cache_def!(state, type: self) do
|
29
|
+
path = state.fetch(:path)
|
30
|
+
properties = fields.to_h do |name, field|
|
31
|
+
type, nilable, meta = field.fetch_values(:type, :nilable, :meta)
|
32
|
+
new_state = {**state, path: [*path, ".#{name}"]}
|
33
|
+
|
34
|
+
schema =
|
35
|
+
case type
|
36
|
+
in Anthropic::Helpers::InputSchema::JsonSchemaConverter
|
37
|
+
type.to_json_schema_inner(state: new_state)
|
38
|
+
else
|
39
|
+
Anthropic::Helpers::InputSchema::JsonSchemaConverter.to_json_schema_inner(
|
40
|
+
type,
|
41
|
+
state: new_state
|
42
|
+
)
|
43
|
+
end
|
44
|
+
Anthropic::Helpers::InputSchema::JsonSchemaConverter.assoc_meta!(schema, meta: meta)
|
45
|
+
schema = Anthropic::Helpers::InputSchema::JsonSchemaConverter.to_nilable(schema) if nilable
|
46
|
+
|
47
|
+
[name, schema]
|
48
|
+
end
|
49
|
+
|
50
|
+
{
|
51
|
+
type: "object",
|
52
|
+
properties: properties,
|
53
|
+
required: fields.select { _2.fetch(:required) }.keys.map(&:to_s),
|
54
|
+
additionalProperties: false
|
55
|
+
}.tap { _1.store(:description, @doc_string) unless @doc_string.nil? }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class << self
|
61
|
+
def required(name_sym, type_info, *args)
|
62
|
+
spec = process_field_args(args)
|
63
|
+
super(name_sym, type_info, spec)
|
64
|
+
end
|
65
|
+
|
66
|
+
def optional(name_sym, type_info, *args)
|
67
|
+
spec = process_field_args(args)
|
68
|
+
super(name_sym, type_info, spec)
|
69
|
+
end
|
70
|
+
|
71
|
+
attr_reader :doc_string
|
72
|
+
|
73
|
+
# @param description [String]
|
74
|
+
def doc(description)
|
75
|
+
@doc_string = description
|
76
|
+
end
|
77
|
+
|
78
|
+
private def process_field_args(args)
|
79
|
+
# Only accept hash format for descriptions.
|
80
|
+
args.grep(Hash).first.to_h
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anthropic
|
4
|
+
module Helpers
|
5
|
+
module InputSchema
|
6
|
+
# @abstract
|
7
|
+
#
|
8
|
+
# Ruby does not have a "boolean" Class, this is something for models to refer to.
|
9
|
+
class Boolean < Anthropic::Internal::Type::Boolean
|
10
|
+
extend Anthropic::Helpers::InputSchema::JsonSchemaConverter
|
11
|
+
|
12
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
13
|
+
|
14
|
+
# @api private
|
15
|
+
#
|
16
|
+
# @param state [Hash{Symbol=>Object}]
|
17
|
+
#
|
18
|
+
# @option state [Hash{Object=>String}] :defs
|
19
|
+
#
|
20
|
+
# @option state [Array<String>] :path
|
21
|
+
#
|
22
|
+
# @return [Hash{Symbol=>Object}]
|
23
|
+
def self.to_json_schema_inner(state:) = {type: "boolean"}
|
24
|
+
|
25
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anthropic
|
4
|
+
module Helpers
|
5
|
+
module InputSchema
|
6
|
+
# @generic Value
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# example = Anthropic::EnumOf[:foo, :bar, :zoo]
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# example = Anthropic::EnumOf[1, 2, 3]
|
13
|
+
class EnumOf
|
14
|
+
include Anthropic::Internal::Type::Enum
|
15
|
+
include Anthropic::Helpers::InputSchema::JsonSchemaConverter
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
# @param state [Hash{Symbol=>Object}]
|
20
|
+
#
|
21
|
+
# @option state [Hash{Object=>String}] :defs
|
22
|
+
#
|
23
|
+
# @option state [Array<String>] :path
|
24
|
+
#
|
25
|
+
# @return [Hash{Symbol=>Object}]
|
26
|
+
def to_json_schema_inner(state:)
|
27
|
+
Anthropic::Helpers::InputSchema::JsonSchemaConverter.cache_def!(state, type: self) do
|
28
|
+
types = values.map do
|
29
|
+
case _1
|
30
|
+
in NilClass
|
31
|
+
"null"
|
32
|
+
in true | false
|
33
|
+
"boolean"
|
34
|
+
in Integer
|
35
|
+
"integer"
|
36
|
+
in Float
|
37
|
+
"number"
|
38
|
+
in Symbol
|
39
|
+
"string"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
.uniq
|
43
|
+
|
44
|
+
{
|
45
|
+
type: types.length == 1 ? types.first : types,
|
46
|
+
enum: values.map { _1.is_a?(Symbol) ? _1.to_s : _1 }
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private_class_method :new
|
52
|
+
|
53
|
+
def self.[](...) = new(...)
|
54
|
+
|
55
|
+
# @return [Array<generic<Value>>]
|
56
|
+
attr_reader :values
|
57
|
+
|
58
|
+
# @param values [Array<generic<Value>>]
|
59
|
+
def initialize(*values) = (@values = values.map { _1.is_a?(String) ? _1.to_sym : _1 })
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anthropic
|
4
|
+
module Helpers
|
5
|
+
module InputSchema
|
6
|
+
# To customize the JSON schema conversion for a type, implement the `JsonSchemaConverter` interface.
|
7
|
+
module JsonSchemaConverter
|
8
|
+
# @api private
|
9
|
+
POINTERS = Object.new.tap do
|
10
|
+
_1.define_singleton_method(:inspect) do
|
11
|
+
"#<#{Anthropic::Helpers::InputSchema::JsonSchemaConverter}::POINTERS>"
|
12
|
+
end
|
13
|
+
end.freeze
|
14
|
+
# @api private
|
15
|
+
NO_REF = Object.new.tap do
|
16
|
+
_1.define_singleton_method(:inspect) do
|
17
|
+
"#<#{Anthropic::Helpers::InputSchema::JsonSchemaConverter}::NO_REF>"
|
18
|
+
end
|
19
|
+
end.freeze
|
20
|
+
|
21
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
22
|
+
|
23
|
+
# The exact JSON schema produced is subject to improvement between minor release versions.
|
24
|
+
#
|
25
|
+
# @param state [Hash{Symbol=>Object}]
|
26
|
+
#
|
27
|
+
# @option state [Hash{Object=>String}] :defs
|
28
|
+
#
|
29
|
+
# @option state [Array<String>] :path
|
30
|
+
#
|
31
|
+
# @return [Hash{Symbol=>Object}]
|
32
|
+
def to_json_schema_inner(state:) = (raise NotImplementedError)
|
33
|
+
|
34
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
35
|
+
|
36
|
+
# Internal helpers methods.
|
37
|
+
class << self
|
38
|
+
# @api private
|
39
|
+
#
|
40
|
+
# @param schema [Hash{Symbol=>Object}]
|
41
|
+
#
|
42
|
+
# @return [Hash{Symbol=>Object}]
|
43
|
+
def to_nilable(schema)
|
44
|
+
null = "null"
|
45
|
+
case schema
|
46
|
+
in {"$ref": String} | {allOf: _}
|
47
|
+
# For references (simple or with allOf pattern for descriptions),
|
48
|
+
# wrap in anyOf with null. The allOf pattern is used when we need
|
49
|
+
# to add a description to a $ref (JSON Schema doesn't allow
|
50
|
+
# additional properties alongside $ref).
|
51
|
+
{anyOf: [schema, {type: null}]}
|
52
|
+
in {anyOf: schemas}
|
53
|
+
null = {type: null}
|
54
|
+
schemas.any? { _1 == null || _1 == {type: ["null"]} } ? schema : {anyOf: [*schemas, null]}
|
55
|
+
in {type: String => type}
|
56
|
+
type == null ? schema : schema.update(type: [type, null])
|
57
|
+
in {type: Array => types}
|
58
|
+
types.include?(null) ? schema : schema.update(type: [*types, null])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @api private
|
63
|
+
#
|
64
|
+
# @param schema [Hash{Symbol=>Object}]
|
65
|
+
def assoc_meta!(schema, meta:)
|
66
|
+
xformed = meta.transform_keys(Anthropic::Helpers::InputSchema::PROPERTY_MAPPING)
|
67
|
+
schema.merge!(xformed)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @api private
|
71
|
+
#
|
72
|
+
# @param state [Hash{Symbol=>Object}]
|
73
|
+
#
|
74
|
+
# @option state [Hash{Object=>String}] :defs
|
75
|
+
#
|
76
|
+
# @option state [Array<String>] :path
|
77
|
+
#
|
78
|
+
# @param type [Object]
|
79
|
+
#
|
80
|
+
# @param blk [Proc]
|
81
|
+
#
|
82
|
+
def cache_def!(state, type:, &blk)
|
83
|
+
defs, path = state.fetch_values(:defs, :path)
|
84
|
+
if (stored = defs[type])
|
85
|
+
pointers = stored.fetch(Anthropic::Helpers::InputSchema::JsonSchemaConverter::POINTERS)
|
86
|
+
pointers.first.except(Anthropic::Helpers::InputSchema::JsonSchemaConverter::NO_REF).tap do
|
87
|
+
pointers << _1
|
88
|
+
end
|
89
|
+
else
|
90
|
+
ref_path = String.new
|
91
|
+
ref = {"$ref": ref_path}
|
92
|
+
stored = {
|
93
|
+
Anthropic::Helpers::InputSchema::JsonSchemaConverter::POINTERS => [ref]
|
94
|
+
}
|
95
|
+
defs.store(type, stored)
|
96
|
+
schema = blk.call
|
97
|
+
ref_path.replace("#/$defs/#{path.join('/')}")
|
98
|
+
stored.update(schema)
|
99
|
+
ref
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# @api private
|
104
|
+
#
|
105
|
+
# @param type [Anthropic::Helpers::InputSchema::JsonSchemaConverter, Class]
|
106
|
+
#
|
107
|
+
# @return [Hash{Symbol=>Object}]
|
108
|
+
def to_json_schema(type)
|
109
|
+
defs = {}
|
110
|
+
state = {defs: defs, path: []}
|
111
|
+
schema = Anthropic::Helpers::InputSchema::JsonSchemaConverter.to_json_schema_inner(
|
112
|
+
type,
|
113
|
+
state: state
|
114
|
+
)
|
115
|
+
reused_defs = {}
|
116
|
+
defs.each_value do |acc|
|
117
|
+
sch = acc.except(Anthropic::Helpers::InputSchema::JsonSchemaConverter::POINTERS)
|
118
|
+
pointers = acc.fetch(Anthropic::Helpers::InputSchema::JsonSchemaConverter::POINTERS)
|
119
|
+
|
120
|
+
no_refs, refs = pointers.partition do
|
121
|
+
_1.delete(Anthropic::Helpers::InputSchema::JsonSchemaConverter::NO_REF)
|
122
|
+
end
|
123
|
+
|
124
|
+
case refs
|
125
|
+
in [ref]
|
126
|
+
ref.replace(ref.except(:$ref).merge(sch))
|
127
|
+
in [_, ref, *]
|
128
|
+
reused_defs.store(ref.fetch(:$ref), sch)
|
129
|
+
refs.each do
|
130
|
+
next if (meta = _1.except(:$ref)).empty?
|
131
|
+
# JSON Schema does not allow keyword properties to be defined alongside a $ref.
|
132
|
+
# If we have a keyword property associated with a $ref, it must be wrapped in an allOf.
|
133
|
+
_1.replace(allOf: [_1.slice(:$ref), meta])
|
134
|
+
end
|
135
|
+
else
|
136
|
+
end
|
137
|
+
no_refs.each { _1.replace(_1.except(:$ref).merge(sch)) }
|
138
|
+
end
|
139
|
+
|
140
|
+
xformed = reused_defs.transform_keys { _1.delete_prefix("#/$defs/") }
|
141
|
+
xformed.empty? ? schema : {"$defs": xformed}.update(schema)
|
142
|
+
end
|
143
|
+
|
144
|
+
# @api private
|
145
|
+
#
|
146
|
+
# @param type [Anthropic::Helpers::InputSchema::JsonSchemaConverter, Class]
|
147
|
+
#
|
148
|
+
# @param state [Hash{Symbol=>Object}]
|
149
|
+
#
|
150
|
+
# @option state [Hash{Object=>String}] :defs
|
151
|
+
#
|
152
|
+
# @option state [Array<String>] :path
|
153
|
+
#
|
154
|
+
# @return [Hash{Symbol=>Object}]
|
155
|
+
def to_json_schema_inner(type, state:)
|
156
|
+
case type
|
157
|
+
in {"$ref": String}
|
158
|
+
return type
|
159
|
+
in Anthropic::Helpers::InputSchema::JsonSchemaConverter
|
160
|
+
return type.to_json_schema_inner(state: state)
|
161
|
+
in Class
|
162
|
+
case type
|
163
|
+
in -> { _1 <= NilClass }
|
164
|
+
return {type: "null"}
|
165
|
+
in -> { _1 <= Integer }
|
166
|
+
return {type: "integer"}
|
167
|
+
in -> { _1 <= Float }
|
168
|
+
return {type: "number"}
|
169
|
+
in -> { _1 <= Symbol || _1 <= String }
|
170
|
+
return {type: "string"}
|
171
|
+
else
|
172
|
+
end
|
173
|
+
in _ if Anthropic::Internal::Util.primitive?(type)
|
174
|
+
return {const: type.is_a?(Symbol) ? type.to_s : type}
|
175
|
+
else
|
176
|
+
end
|
177
|
+
|
178
|
+
models = %w[
|
179
|
+
NilClass
|
180
|
+
String
|
181
|
+
Symbol
|
182
|
+
Integer
|
183
|
+
Float
|
184
|
+
Anthropic::Boolean
|
185
|
+
Anthropic::ArrayOf
|
186
|
+
Anthropic::EnumOf
|
187
|
+
Anthropic::UnionOf
|
188
|
+
Anthropic::BaseModel
|
189
|
+
]
|
190
|
+
# rubocop:disable Layout/LineLength
|
191
|
+
message = "#{type} does not implement the #{Anthropic::Helpers::InputSchema::JsonSchemaConverter} interface. Please use one of the supported types: #{models}"
|
192
|
+
# rubocop:enable Layout/LineLength
|
193
|
+
raise ArgumentError.new(message)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anthropic
|
4
|
+
module Helpers
|
5
|
+
module InputSchema
|
6
|
+
# @abstract
|
7
|
+
#
|
8
|
+
# Like Anthropic::Internal::Type::Unknown, but for parsed JSON values, which can be incomplete or malformed.
|
9
|
+
class ParsedJson < Anthropic::Internal::Type::Unknown
|
10
|
+
class << self
|
11
|
+
# @api private
|
12
|
+
#
|
13
|
+
# No coercion needed for Unknown type.
|
14
|
+
#
|
15
|
+
# @param value [Object]
|
16
|
+
#
|
17
|
+
# @param state [Hash{Symbol=>Object}] .
|
18
|
+
#
|
19
|
+
# @option state [Boolean] :translate_names
|
20
|
+
#
|
21
|
+
# @option state [Boolean] :strictness
|
22
|
+
#
|
23
|
+
# @option state [Hash{Symbol=>Object}] :exactness
|
24
|
+
#
|
25
|
+
# @option state [Class<StandardError>] :error
|
26
|
+
#
|
27
|
+
# @option state [Integer] :branched
|
28
|
+
#
|
29
|
+
# @return [Object]
|
30
|
+
def coerce(value, state:)
|
31
|
+
(state[:error] = value) if value.is_a?(StandardError)
|
32
|
+
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anthropic
|
4
|
+
module Helpers
|
5
|
+
module InputSchema
|
6
|
+
# rubocop:disable Style/MutableConstant
|
7
|
+
PROPERTY_MAPPING = {
|
8
|
+
# Numeric properties:
|
9
|
+
minimum: :minimum,
|
10
|
+
maximum: :maximum,
|
11
|
+
exclusive_minimum: :exclusiveMinimum,
|
12
|
+
exclusive_maximum: :exclusiveMaximum,
|
13
|
+
multiple_of: :multipleOf,
|
14
|
+
|
15
|
+
# String properties:
|
16
|
+
min_length: :minLength,
|
17
|
+
max_length: :maxLength,
|
18
|
+
pattern: :pattern,
|
19
|
+
format: :format,
|
20
|
+
content_media_type: :contentMediaType,
|
21
|
+
content_encoding: :contentEncoding,
|
22
|
+
|
23
|
+
# Array properties:
|
24
|
+
min_items: :minItems,
|
25
|
+
max_items: :maxItems,
|
26
|
+
unique_items: :uniqueItems,
|
27
|
+
prefix_items: :prefixItems,
|
28
|
+
contains: :contains,
|
29
|
+
min_contains: :minContains,
|
30
|
+
max_contains: :maxContains,
|
31
|
+
|
32
|
+
# Object properties:
|
33
|
+
pattern_properties: :patternProperties,
|
34
|
+
dependent_schemas: :dependentSchemas,
|
35
|
+
dependent_required: :dependentRequired,
|
36
|
+
property_names: :propertyNames,
|
37
|
+
|
38
|
+
# Metadata:
|
39
|
+
default: :default,
|
40
|
+
examples: :examples,
|
41
|
+
|
42
|
+
doc: :description
|
43
|
+
}
|
44
|
+
# rubocop:enable Style/MutableConstant
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anthropic
|
4
|
+
module Helpers
|
5
|
+
module InputSchema
|
6
|
+
# @generic Member
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# example = Anthropic::UnionOf[Float, Anthropic::ArrayOf[Integer]]
|
10
|
+
class UnionOf
|
11
|
+
include Anthropic::Internal::Type::Union
|
12
|
+
include Anthropic::Helpers::InputSchema::JsonSchemaConverter
|
13
|
+
|
14
|
+
# @api private
|
15
|
+
#
|
16
|
+
# @param state [Hash{Symbol=>Object}]
|
17
|
+
#
|
18
|
+
# @option state [Hash{Object=>String}] :defs
|
19
|
+
#
|
20
|
+
# @option state [Array<String>] :path
|
21
|
+
#
|
22
|
+
# @return [Hash{Symbol=>Object}]
|
23
|
+
def to_json_schema_inner(state:)
|
24
|
+
Anthropic::Helpers::InputSchema::JsonSchemaConverter.cache_def!(state, type: self) do
|
25
|
+
path = state.fetch(:path)
|
26
|
+
mergeable_keys = {[:anyOf] => 0, [:type] => 0}
|
27
|
+
schemas = variants.to_enum.with_index.map do
|
28
|
+
new_state = {**state, path: [*path, "?.#{_2}"]}
|
29
|
+
Anthropic::Helpers::InputSchema::JsonSchemaConverter.to_json_schema_inner(
|
30
|
+
_1,
|
31
|
+
state: new_state
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
schemas.each do |schema|
|
36
|
+
mergeable_keys.each_key { mergeable_keys[_1] += 1 if schema.keys == _1 }
|
37
|
+
end
|
38
|
+
mergeable = mergeable_keys.any? { _1.last == schemas.length }
|
39
|
+
mergeable ? Anthropic::Internal::Util.deep_merge(*schemas, concat: true) : {anyOf: schemas}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private_class_method :new
|
44
|
+
|
45
|
+
def self.[](...) = new(...)
|
46
|
+
|
47
|
+
# @param variants [Array<generic<Member>>]
|
48
|
+
def initialize(*variants)
|
49
|
+
variants.each do |v|
|
50
|
+
v.is_a?(Proc) ? variant(v) : variant(-> { v })
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anthropic
|
4
|
+
module Helpers
|
5
|
+
# Helpers for the structured output API.
|
6
|
+
#
|
7
|
+
# see https://platform.Anthropic.com/docs/guides/structured-outputs
|
8
|
+
# see https://json-schema.org
|
9
|
+
#
|
10
|
+
# Based on the DSL in {Anthropic::Internal::Type}, but currently only support the limited subset of JSON schema types used in structured output APIs.
|
11
|
+
#
|
12
|
+
# Supported types: {NilClass} {String} {Symbol} {Integer} {Float} {Anthropic::Boolean}, {Anthropic::EnumOf}, {Anthropic::UnionOf}, {Anthropic::ArrayOf}, {Anthropic::BaseModel}
|
13
|
+
module InputSchema
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|