omniai-anthropic 1.9.5 → 1.9.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +12 -11
- data/lib/omniai/anthropic/chat/content_serializer.rb +3 -3
- data/lib/omniai/anthropic/chat/function_serializer.rb +2 -2
- data/lib/omniai/anthropic/chat/media_serializer.rb +1 -1
- data/lib/omniai/anthropic/chat/message_serializer.rb +3 -3
- data/lib/omniai/anthropic/chat/payload_serializer.rb +1 -1
- data/lib/omniai/anthropic/chat/stream.rb +11 -11
- data/lib/omniai/anthropic/chat/text_serializer.rb +2 -2
- data/lib/omniai/anthropic/chat/tool_call_result_serializer.rb +3 -3
- data/lib/omniai/anthropic/chat/tool_call_serializer.rb +2 -2
- data/lib/omniai/anthropic/chat.rb +17 -17
- data/lib/omniai/anthropic/client.rb +4 -4
- data/lib/omniai/anthropic/computer.rb +29 -29
- data/lib/omniai/anthropic/config.rb +6 -6
- data/lib/omniai/anthropic/version.rb +1 -1
- data/lib/omniai/anthropic.rb +3 -3
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbc0621a00cb26d51c8d89012eb0e15df9617d4336856009faa623a44d03931a
|
4
|
+
data.tar.gz: 8e59840a199ce6008721afd118204830f275429d80b518ce6157e5706e53f017
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93734d2b56554140b6ee65db3e5af042ce354f5d4b54a264399d4b9f7ddd2bc913cf21086a3f8e312e3eb0fa5e1b5cf1767c3a745361e1aa64a5d2e33925a1cd
|
7
|
+
data.tar.gz: 15b5377a7c1aaa4bb58641cec3f7353034f198d668eb38a46d88a1ab1aadba94bad32fa39d94c67eec4e8c5020a016e05c62e7772db99d0f20d4fd145c253856
|
data/Gemfile
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
source
|
3
|
+
source "https://rubygems.org"
|
4
4
|
|
5
5
|
gemspec
|
6
6
|
|
7
|
-
gem
|
8
|
-
gem
|
9
|
-
gem
|
10
|
-
gem
|
11
|
-
gem
|
12
|
-
gem
|
13
|
-
gem
|
14
|
-
gem
|
15
|
-
gem
|
16
|
-
gem
|
7
|
+
gem "logger"
|
8
|
+
gem "rake"
|
9
|
+
gem "rspec"
|
10
|
+
gem "rspec_junit_formatter"
|
11
|
+
gem "rubocop"
|
12
|
+
gem "rubocop-basic"
|
13
|
+
gem "rubocop-rake"
|
14
|
+
gem "rubocop-rspec"
|
15
|
+
gem "simplecov"
|
16
|
+
gem "webmock"
|
17
|
+
gem "yard"
|
@@ -9,9 +9,9 @@ module OmniAI
|
|
9
9
|
# @param context [Context]
|
10
10
|
# @return [OmniAI::Chat::Text, OmniAI::Chat::ToolCall]
|
11
11
|
def self.deserialize(data, context:)
|
12
|
-
case data[
|
13
|
-
when
|
14
|
-
when
|
12
|
+
case data["type"]
|
13
|
+
when "text" then OmniAI::Chat::Text.deserialize(data, context:)
|
14
|
+
when "tool_use" then OmniAI::Chat::ToolCall.deserialize(data, context:)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -17,8 +17,8 @@ module OmniAI
|
|
17
17
|
# @param data [Hash]
|
18
18
|
# @return [OmniAI::Chat::Function]
|
19
19
|
def self.deserialize(data, *)
|
20
|
-
name = data[
|
21
|
-
arguments = data[
|
20
|
+
name = data["name"]
|
21
|
+
arguments = data["input"]
|
22
22
|
OmniAI::Chat::Function.new(name:, arguments:)
|
23
23
|
end
|
24
24
|
end
|
@@ -13,7 +13,7 @@ module OmniAI
|
|
13
13
|
parts = arrayify(message.content) + arrayify(message.tool_call_list)
|
14
14
|
content = parts.map do |part|
|
15
15
|
case part
|
16
|
-
when String then { type:
|
16
|
+
when String then { type: "text", text: part }
|
17
17
|
else part.serialize(context:)
|
18
18
|
end
|
19
19
|
end
|
@@ -25,8 +25,8 @@ module OmniAI
|
|
25
25
|
# @param context [OmniAI::Context]
|
26
26
|
# @return [OmniAI::Chat::Message]
|
27
27
|
def self.deserialize(data, context:)
|
28
|
-
role = data[
|
29
|
-
parts = arrayify(data[
|
28
|
+
role = data["role"]
|
29
|
+
parts = arrayify(data["content"]).map do |content|
|
30
30
|
ContentSerializer.deserialize(content, context:)
|
31
31
|
end
|
32
32
|
|
@@ -19,7 +19,7 @@ module OmniAI
|
|
19
19
|
# @param context [OmniAI::Context]
|
20
20
|
# @return [OmniAI::Chat::Payload]
|
21
21
|
def self.deserialize(data, context:)
|
22
|
-
usage = OmniAI::Chat::Usage.deserialize(data[
|
22
|
+
usage = OmniAI::Chat::Usage.deserialize(data["usage"], context:) if data["usage"]
|
23
23
|
choice = OmniAI::Chat::Choice.deserialize(data, context:)
|
24
24
|
|
25
25
|
OmniAI::Chat::Payload.new(choices: [choice], usage:)
|
@@ -6,13 +6,13 @@ module OmniAI
|
|
6
6
|
# A stream given when streaming.
|
7
7
|
class Stream < OmniAI::Chat::Stream
|
8
8
|
module Type
|
9
|
-
PING =
|
10
|
-
MESSAGE_START =
|
11
|
-
MESSAGE_STOP =
|
12
|
-
MESSAGE_DELTA =
|
13
|
-
CONTENT_BLOCK_START =
|
14
|
-
CONTENT_BLOCK_STOP =
|
15
|
-
CONTENT_BLOCK_DELTA =
|
9
|
+
PING = "ping"
|
10
|
+
MESSAGE_START = "message_start"
|
11
|
+
MESSAGE_STOP = "message_stop"
|
12
|
+
MESSAGE_DELTA = "message_delta"
|
13
|
+
CONTENT_BLOCK_START = "content_block_start"
|
14
|
+
CONTENT_BLOCK_STOP = "content_block_stop"
|
15
|
+
CONTENT_BLOCK_DELTA = "content_block_delta"
|
16
16
|
end
|
17
17
|
|
18
18
|
# Process the stream into chunks by event.
|
@@ -22,7 +22,7 @@ module OmniAI
|
|
22
22
|
return unless @content
|
23
23
|
|
24
24
|
OmniAI::Chat::Payload.deserialize(@message.merge({
|
25
|
-
|
25
|
+
"content" => @content,
|
26
26
|
}), context:)
|
27
27
|
end
|
28
28
|
|
@@ -30,7 +30,7 @@ module OmniAI
|
|
30
30
|
#
|
31
31
|
# @param data [Hash]
|
32
32
|
def message_start(data)
|
33
|
-
@message = data[
|
33
|
+
@message = data["message"]
|
34
34
|
end
|
35
35
|
|
36
36
|
# Handler for Type::MESSAGE_STOP
|
@@ -58,11 +58,11 @@ module OmniAI
|
|
58
58
|
#
|
59
59
|
# @param data [Hash]
|
60
60
|
def content_block_delta(data)
|
61
|
-
@content = [{
|
61
|
+
@content = [{ "type" => "text", "text" => data["delta"]["text"] }]
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
|
65
|
+
protected
|
66
66
|
|
67
67
|
def builder
|
68
68
|
@builder ||= Builder.new
|
@@ -8,13 +8,13 @@ module OmniAI
|
|
8
8
|
# @param text [OmniAI::Chat::Text]
|
9
9
|
# @return [Hash]
|
10
10
|
def self.serialize(text, *)
|
11
|
-
{ type:
|
11
|
+
{ type: "text", text: text.text }
|
12
12
|
end
|
13
13
|
|
14
14
|
# @param data [Hash]
|
15
15
|
# @return [OmniAI::Chat::Text]
|
16
16
|
def self.deserialize(data, *)
|
17
|
-
OmniAI::Chat::Text.new(data[
|
17
|
+
OmniAI::Chat::Text.new(data["text"])
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -9,7 +9,7 @@ module OmniAI
|
|
9
9
|
# @return [Hash]
|
10
10
|
def self.serialize(tool_call_result, *)
|
11
11
|
{
|
12
|
-
type:
|
12
|
+
type: "tool_result",
|
13
13
|
tool_use_id: tool_call_result.tool_call_id,
|
14
14
|
content: tool_call_result.content,
|
15
15
|
}
|
@@ -18,8 +18,8 @@ module OmniAI
|
|
18
18
|
# @param data [Hash]
|
19
19
|
# @return [OmniAI::Chat::ToolCallResult]
|
20
20
|
def self.deserialize(data, *)
|
21
|
-
tool_call_id = data[
|
22
|
-
content = data[
|
21
|
+
tool_call_id = data["tool_use_id"]
|
22
|
+
content = data["content"]
|
23
23
|
|
24
24
|
OmniAI::Chat::ToolCallResult.new(content:, tool_call_id:)
|
25
25
|
end
|
@@ -12,7 +12,7 @@ module OmniAI
|
|
12
12
|
function = tool_call.function.serialize(context:)
|
13
13
|
{
|
14
14
|
id: tool_call.id,
|
15
|
-
type:
|
15
|
+
type: "tool_use",
|
16
16
|
}.merge(function)
|
17
17
|
end
|
18
18
|
|
@@ -21,7 +21,7 @@ module OmniAI
|
|
21
21
|
# @return [OmniAI::Chat::ToolCall]
|
22
22
|
def self.deserialize(data, context:)
|
23
23
|
function = OmniAI::Chat::Function.deserialize(data, context:)
|
24
|
-
OmniAI::Chat::ToolCall.new(id: data[
|
24
|
+
OmniAI::Chat::ToolCall.new(id: data["id"], function:)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -13,21 +13,21 @@ module OmniAI
|
|
13
13
|
# completion.text # '...'
|
14
14
|
class Chat < OmniAI::Chat
|
15
15
|
module Model
|
16
|
-
CLAUDE_INSTANT_1_0 =
|
17
|
-
CLAUDE_2_0 =
|
18
|
-
CLAUDE_2_1 =
|
19
|
-
|
20
|
-
CLAUDE_3_HAIKU_20240307 =
|
21
|
-
CLAUDE_3_5_HAIKU_20241022 =
|
22
|
-
CLAUDE_3_OPUS_20240229 =
|
23
|
-
CLAUDE_3_SONNET_20240209 =
|
24
|
-
CLAUDE_3_SONNET_20240307 =
|
25
|
-
CLAUDE_3_5_SONNET_20240620 =
|
26
|
-
CLAUDE_3_5_SONNET_20241022 =
|
27
|
-
|
28
|
-
CLAUDE_3_5_HAIKU_LATEST =
|
29
|
-
CLAUDE_3_OPUS_LATEST =
|
30
|
-
CLAUDE_3_5_SONNET_LATEST =
|
16
|
+
CLAUDE_INSTANT_1_0 = "claude-instant-1.2"
|
17
|
+
CLAUDE_2_0 = "claude-2.0"
|
18
|
+
CLAUDE_2_1 = "claude-2.1"
|
19
|
+
|
20
|
+
CLAUDE_3_HAIKU_20240307 = "claude-3-haiku-20240307"
|
21
|
+
CLAUDE_3_5_HAIKU_20241022 = "claude-3-5-haiku-20241022"
|
22
|
+
CLAUDE_3_OPUS_20240229 = "claude-3-opus-20240229"
|
23
|
+
CLAUDE_3_SONNET_20240209 = "claude-3-sonnet-20240229"
|
24
|
+
CLAUDE_3_SONNET_20240307 = "claude-3-sonnet-20240307"
|
25
|
+
CLAUDE_3_5_SONNET_20240620 = "claude-3-5-sonnet-20240620"
|
26
|
+
CLAUDE_3_5_SONNET_20241022 = "claude-3-5-sonnet-20241022"
|
27
|
+
|
28
|
+
CLAUDE_3_5_HAIKU_LATEST = "claude-3-5-haiku-latest"
|
29
|
+
CLAUDE_3_OPUS_LATEST = "claude-3-opus-latest"
|
30
|
+
CLAUDE_3_5_SONNET_LATEST = "claude-3-5-sonnet-latest"
|
31
31
|
|
32
32
|
CLAUDE_HAIKU = CLAUDE_3_5_HAIKU_LATEST
|
33
33
|
CLAUDE_OPUS = CLAUDE_3_OPUS_LATEST
|
@@ -93,7 +93,7 @@ module OmniAI
|
|
93
93
|
"/#{Client::VERSION}/messages"
|
94
94
|
end
|
95
95
|
|
96
|
-
|
96
|
+
protected
|
97
97
|
|
98
98
|
# @return [Context]
|
99
99
|
def context
|
@@ -109,7 +109,7 @@ module OmniAI
|
|
109
109
|
[Message.new(role: OmniAI::Chat::Role::USER, content:)]
|
110
110
|
end
|
111
111
|
|
112
|
-
|
112
|
+
private
|
113
113
|
|
114
114
|
# @return [Array<Hash>, nil]
|
115
115
|
def tools_payload
|
@@ -20,7 +20,7 @@ module OmniAI
|
|
20
20
|
#
|
21
21
|
# client = OmniAI::Anthropic::Client.new
|
22
22
|
class Client < OmniAI::Client
|
23
|
-
VERSION =
|
23
|
+
VERSION = "v1"
|
24
24
|
|
25
25
|
# @param api_key [String] optional - defaults to `OmniAI::Anthropic.config.api_key`
|
26
26
|
# @param host [String] optional - defaults to `OmniAI::Anthropic.config.host`
|
@@ -48,9 +48,9 @@ module OmniAI
|
|
48
48
|
# @return [HTTP::Client]
|
49
49
|
def connection
|
50
50
|
@connection ||= super.headers({
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
"x-api-key": @api_key,
|
52
|
+
"anthropic-version": @version,
|
53
|
+
"anthropic-beta": @beta,
|
54
54
|
}.compact)
|
55
55
|
end
|
56
56
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "open3"
|
4
4
|
|
5
5
|
module OmniAI
|
6
6
|
module Anthropic
|
@@ -11,24 +11,24 @@ module OmniAI
|
|
11
11
|
#
|
12
12
|
# computer = OmniAI::Anthropic::Computer.new()
|
13
13
|
class Computer
|
14
|
-
TYPE =
|
14
|
+
TYPE = "computer_20241022"
|
15
15
|
|
16
16
|
SCREENSHOT_DELAY = 2.0 # seconds
|
17
17
|
TYPING_DELAY = 20 # milliseconds
|
18
18
|
|
19
19
|
module Action
|
20
|
-
KEY =
|
21
|
-
TYPE =
|
22
|
-
CURSOR_POSITION =
|
23
|
-
MOUSE_MOVE =
|
24
|
-
LEFT_CLICK =
|
25
|
-
RIGHT_CLICK =
|
26
|
-
MIDDLE_CLICK =
|
27
|
-
LEFT_CLICK_DRAG =
|
28
|
-
RIGHT_CLICK_DRAG =
|
29
|
-
MIDDLE_CLICK_DRAG =
|
30
|
-
DOUBLE_CLICK =
|
31
|
-
SCREENSHOT =
|
20
|
+
KEY = "key"
|
21
|
+
TYPE = "type"
|
22
|
+
CURSOR_POSITION = "cursor_position"
|
23
|
+
MOUSE_MOVE = "mouse_move"
|
24
|
+
LEFT_CLICK = "left_click"
|
25
|
+
RIGHT_CLICK = "right_click"
|
26
|
+
MIDDLE_CLICK = "middle_click"
|
27
|
+
LEFT_CLICK_DRAG = "left_click_drag"
|
28
|
+
RIGHT_CLICK_DRAG = "right_click_drag"
|
29
|
+
MIDDLE_CLICK_DRAG = "middle_click_drag"
|
30
|
+
DOUBLE_CLICK = "double_click"
|
31
|
+
SCREENSHOT = "screenshot"
|
32
32
|
end
|
33
33
|
|
34
34
|
module Button
|
@@ -45,7 +45,7 @@ module OmniAI
|
|
45
45
|
# @param display_width_px [Integer]
|
46
46
|
# @param display_height_px [Integer]
|
47
47
|
# @param display_number [Integer] optional
|
48
|
-
def initialize(display_width_px:, display_height_px:, display_number: 1, name:
|
48
|
+
def initialize(display_width_px:, display_height_px:, display_number: 1, name: "computer")
|
49
49
|
@name = name
|
50
50
|
@display_width_px = display_width_px
|
51
51
|
@display_height_px = display_height_px
|
@@ -80,9 +80,9 @@ module OmniAI
|
|
80
80
|
# @return [String]
|
81
81
|
def call(args = {})
|
82
82
|
perform(
|
83
|
-
action: args[
|
84
|
-
text: args[
|
85
|
-
coordinate: args[
|
83
|
+
action: args["action"],
|
84
|
+
text: args["text"],
|
85
|
+
coordinate: args["coordinate"]
|
86
86
|
)
|
87
87
|
end
|
88
88
|
|
@@ -121,21 +121,21 @@ module OmniAI
|
|
121
121
|
#
|
122
122
|
# @return [String]
|
123
123
|
def xdotool(...)
|
124
|
-
shell(
|
124
|
+
shell("xdotool", ...)
|
125
125
|
end
|
126
126
|
|
127
127
|
# @param button [Integer]
|
128
128
|
#
|
129
129
|
# @return [String]
|
130
130
|
def click(button:)
|
131
|
-
xdotool(
|
131
|
+
xdotool("click", button)
|
132
132
|
end
|
133
133
|
|
134
134
|
# @param button [Integer]
|
135
135
|
#
|
136
136
|
# @return [String]
|
137
137
|
def double_click(button:)
|
138
|
-
xdotool(
|
138
|
+
xdotool("click", button, "--repeat", 2)
|
139
139
|
end
|
140
140
|
|
141
141
|
# @param coordinate [Array] [x, y]
|
@@ -143,7 +143,7 @@ module OmniAI
|
|
143
143
|
# @return [String]
|
144
144
|
def mouse_move(coordinate:)
|
145
145
|
x, y = coordinate
|
146
|
-
xdotool(
|
146
|
+
xdotool("mousemove", "--sync", x, y)
|
147
147
|
end
|
148
148
|
|
149
149
|
# @param coordinate [Array] [x, y]
|
@@ -152,12 +152,12 @@ module OmniAI
|
|
152
152
|
# @return [String]
|
153
153
|
def mouse_down_move_up(coordinate:, button:)
|
154
154
|
x, y = coordinate
|
155
|
-
xdotool(
|
155
|
+
xdotool("mousedown", button, "mousemove", "--sync", x, y, "mouseup", button)
|
156
156
|
end
|
157
157
|
|
158
158
|
# @return [String]
|
159
159
|
def mouse_location
|
160
|
-
xdotool(
|
160
|
+
xdotool("getmouselocation")
|
161
161
|
end
|
162
162
|
|
163
163
|
# @param text [String]
|
@@ -165,24 +165,24 @@ module OmniAI
|
|
165
165
|
#
|
166
166
|
# @return [String]
|
167
167
|
def type(text:, delay: TYPING_DELAY)
|
168
|
-
xdotool(
|
168
|
+
xdotool("type", "--delay", delay, "--", text)
|
169
169
|
end
|
170
170
|
|
171
171
|
# @param text [String]
|
172
172
|
#
|
173
173
|
# @return [String]
|
174
174
|
def key(text:)
|
175
|
-
xdotool(
|
175
|
+
xdotool("key", "--", text)
|
176
176
|
end
|
177
177
|
|
178
178
|
# @return [Hash]
|
179
179
|
def screenshot
|
180
|
-
tempfile = Tempfile.new([
|
181
|
-
Kernel.system(
|
180
|
+
tempfile = Tempfile.new(["screenshot", ".png"])
|
181
|
+
Kernel.system("gnome-screenshot", "-w", "-f", tempfile.path)
|
182
182
|
tempfile.rewind
|
183
183
|
data = Base64.encode64(tempfile.read)
|
184
184
|
|
185
|
-
{ type:
|
185
|
+
{ type: "base64", media_type: "image/png", data: data }
|
186
186
|
ensure
|
187
187
|
tempfile.close
|
188
188
|
tempfile.unlink
|
@@ -4,8 +4,8 @@ module OmniAI
|
|
4
4
|
module Anthropic
|
5
5
|
# Configuration for Anthropic.
|
6
6
|
class Config < OmniAI::Config
|
7
|
-
DEFAULT_HOST =
|
8
|
-
DEFAULT_VERSION =
|
7
|
+
DEFAULT_HOST = "https://api.anthropic.com"
|
8
|
+
DEFAULT_VERSION = "2023-06-01"
|
9
9
|
|
10
10
|
# @!attribute [rw] version
|
11
11
|
# @return [String, nil] passed as `anthropic-version` if specified
|
@@ -22,10 +22,10 @@ module OmniAI
|
|
22
22
|
# @param logger [Logger, nil] optional - defaults to
|
23
23
|
# @param timeout [Integer, Hash, nil] optional
|
24
24
|
def initialize(
|
25
|
-
api_key: ENV.fetch(
|
26
|
-
host: ENV.fetch(
|
27
|
-
version: ENV.fetch(
|
28
|
-
beta: ENV.fetch(
|
25
|
+
api_key: ENV.fetch("ANTHROPIC_API_KEY", nil),
|
26
|
+
host: ENV.fetch("ANTHROPIC_HOST", DEFAULT_HOST),
|
27
|
+
version: ENV.fetch("ANTHROPIC_VERSION", DEFAULT_VERSION),
|
28
|
+
beta: ENV.fetch("ANTHROPIC_BETA", nil),
|
29
29
|
logger: nil,
|
30
30
|
timeout: nil
|
31
31
|
)
|
data/lib/omniai/anthropic.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omniai-anthropic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.9.
|
4
|
+
version: 1.9.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Sylvestre
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-01-18 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: event_stream_parser
|
@@ -85,7 +84,6 @@ metadata:
|
|
85
84
|
homepage_uri: https://github.com/ksylvest/omniai-anthropic
|
86
85
|
changelog_uri: https://github.com/ksylvest/omniai-anthropic/releases
|
87
86
|
rubygems_mfa_required: 'true'
|
88
|
-
post_install_message:
|
89
87
|
rdoc_options: []
|
90
88
|
require_paths:
|
91
89
|
- lib
|
@@ -100,8 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
98
|
- !ruby/object:Gem::Version
|
101
99
|
version: '0'
|
102
100
|
requirements: []
|
103
|
-
rubygems_version: 3.
|
104
|
-
signing_key:
|
101
|
+
rubygems_version: 3.6.2
|
105
102
|
specification_version: 4
|
106
103
|
summary: A generalized framework for interacting with Anthropic
|
107
104
|
test_files: []
|