ai-chat 0.0.4 → 0.0.7
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 +17 -0
- data/README.md +35 -2
- data/lib/ai/chat/version.rb +1 -1
- data/lib/ai/chat.rb +95 -31
- data/test_program/test_ai_chat.rb +67 -6
- metadata +18 -6
- data/.rspec_status +0 -16
- data/ai_chat.gemspec +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80aebb03e5962c921d6f5e47ee1521b760ffabe223869141eaa0b1d6b53514c0
|
4
|
+
data.tar.gz: 53fb9565b1e41a7bf5b93bd85cabe09af0be5028a163612bc440298aef4a01df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1216d345bb460a00a9baf6555fc60d1337ee2ac73590fb6ec8d5a0af839a7eca664dfc83f94f5b7f1898217ad67d8ecd314c911874d4affbbcc3d5f1d8ab3f75
|
7
|
+
data.tar.gz: a8bcf3c0f3edadfc6ba9398220214fd9c90c0bfa2ec9a4ad5c3f54c957b0a30a5c5d6df4beb36cfd8df86e2defd4117acd827c52387710e9246e6e8649e1ccfa
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.0.7] - 2025-04-25
|
4
|
+
|
5
|
+
- Added support for reasoning effort parameter (`reasoning_effort`) with the OpenAI Responses API
|
6
|
+
- Support for reasoning models like o3, o4-mini
|
7
|
+
- Updated documentation with examples
|
8
|
+
|
9
|
+
## [0.0.6] - 2025-04-25
|
10
|
+
|
11
|
+
- Fixed minor bugs
|
12
|
+
- Improved error handling
|
13
|
+
|
14
|
+
## [0.0.5] - 2025-04-25
|
15
|
+
|
16
|
+
- Updated to use OpenAI's Responses API instead of Chat Completions API
|
17
|
+
- Fixed image processing to work with the new API format
|
18
|
+
- Improved error handling and response parsing
|
19
|
+
|
3
20
|
## [0.0.1] - 2025-02-27
|
4
21
|
|
5
22
|
- Initial release
|
data/README.md
CHANGED
@@ -154,12 +154,45 @@ Useful if you are reconstructing a chat that has already happened.
|
|
154
154
|
- You can call `.messages` to get an array containing the conversation so far.
|
155
155
|
- TODO: Setting `.messages` will replace the conversation with the provided array.
|
156
156
|
|
157
|
+
## Testing with Real API Calls
|
158
|
+
|
159
|
+
While this gem includes specs, they use mocked API responses. To test with real API calls:
|
160
|
+
|
161
|
+
1. Navigate to the test program directory: `cd test_program`
|
162
|
+
2. Create a `.env` file in the test_program directory with your API credentials:
|
163
|
+
```
|
164
|
+
# Your OpenAI API key
|
165
|
+
OPENAI_API_KEY=your_openai_api_key_here
|
166
|
+
```
|
167
|
+
3. Install dependencies: `bundle install`
|
168
|
+
4. Run the test program: `ruby test_ai_chat.rb`
|
169
|
+
|
170
|
+
This test program runs through all the major features of the gem, making real API calls to OpenAI.
|
171
|
+
|
172
|
+
## Reasoning Effort
|
173
|
+
|
174
|
+
When using reasoning models like `o3` or `o4-mini`, you can specify a reasoning effort level to control how much reasoning the model does before producing its final response:
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
x = AI::Chat.new
|
178
|
+
x.model = "o4-mini"
|
179
|
+
x.reasoning_effort = "medium" # Can be "low", "medium", or "high"
|
180
|
+
|
181
|
+
x.user("Write a bash script that transposes a matrix represented as '[1,2],[3,4],[5,6]'")
|
182
|
+
x.assistant!
|
183
|
+
```
|
184
|
+
|
185
|
+
The `reasoning_effort` parameter guides the model on how many reasoning tokens to generate before creating a response to the prompt. Options are:
|
186
|
+
- `"low"`: Favors speed and economical token usage
|
187
|
+
- `"medium"`: (Default) Balances speed and reasoning accuracy
|
188
|
+
- `"high"`: Favors more complete reasoning
|
189
|
+
|
190
|
+
Setting to `nil` disables the reasoning parameter.
|
191
|
+
|
157
192
|
## TODOs
|
158
193
|
|
159
|
-
- Add a `reasoning_effort` parameter.
|
160
194
|
- Add the ability to set all messages at once, ideally with an ActiveRecord Relation.
|
161
195
|
- Add a way to access the whole API response body (rather than just the message content).
|
162
|
-
- Add specs.
|
163
196
|
|
164
197
|
## Contributing
|
165
198
|
|
data/lib/ai/chat/version.rb
CHANGED
data/lib/ai/chat.rb
CHANGED
@@ -5,11 +5,31 @@
|
|
5
5
|
module AI
|
6
6
|
class Chat
|
7
7
|
attr_accessor :messages, :schema, :model
|
8
|
+
attr_reader :reasoning_effort
|
9
|
+
|
10
|
+
VALID_REASONING_EFFORTS = [:low, :medium, :high].freeze
|
8
11
|
|
9
12
|
def initialize(api_key: nil)
|
10
13
|
@api_key = api_key || ENV.fetch("OPENAI_API_KEY")
|
11
14
|
@messages = []
|
12
15
|
@model = "gpt-4.1-mini"
|
16
|
+
@reasoning_effort = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def reasoning_effort=(value)
|
20
|
+
if value.nil?
|
21
|
+
@reasoning_effort = nil
|
22
|
+
else
|
23
|
+
# Convert string to symbol if needed
|
24
|
+
symbol_value = value.is_a?(String) ? value.to_sym : value
|
25
|
+
|
26
|
+
if VALID_REASONING_EFFORTS.include?(symbol_value)
|
27
|
+
@reasoning_effort = symbol_value
|
28
|
+
else
|
29
|
+
valid_values = VALID_REASONING_EFFORTS.map { |v| ":#{v} or \"#{v}\"" }.join(", ")
|
30
|
+
raise ArgumentError, "Invalid reasoning_effort value: '#{value}'. Must be one of: #{valid_values}"
|
31
|
+
end
|
32
|
+
end
|
13
33
|
end
|
14
34
|
|
15
35
|
def system(content)
|
@@ -22,15 +42,13 @@ module AI
|
|
22
42
|
if item.key?("image") || item.key?(:image)
|
23
43
|
image_value = item.fetch("image") { item.fetch(:image) }
|
24
44
|
{
|
25
|
-
type: "
|
26
|
-
image_url:
|
27
|
-
url: process_image(image_value)
|
28
|
-
}
|
45
|
+
type: "input_image",
|
46
|
+
image_url: process_image(image_value)
|
29
47
|
}
|
30
48
|
elsif item.key?("text") || item.key?(:text)
|
31
49
|
text_value = item.fetch("text") { item.fetch(:text) }
|
32
50
|
{
|
33
|
-
type: "
|
51
|
+
type: "input_text",
|
34
52
|
text: text_value
|
35
53
|
}
|
36
54
|
else
|
@@ -54,7 +72,7 @@ module AI
|
|
54
72
|
else
|
55
73
|
text_and_images_array = [
|
56
74
|
{
|
57
|
-
type: "
|
75
|
+
type: "input_text",
|
58
76
|
text: content
|
59
77
|
}
|
60
78
|
]
|
@@ -62,10 +80,8 @@ module AI
|
|
62
80
|
if images && !images.empty?
|
63
81
|
images_array = images.map do |image|
|
64
82
|
{
|
65
|
-
type: "
|
66
|
-
image_url:
|
67
|
-
url: process_image(image)
|
68
|
-
}
|
83
|
+
type: "input_image",
|
84
|
+
image_url: process_image(image)
|
69
85
|
}
|
70
86
|
end
|
71
87
|
|
@@ -73,10 +89,8 @@ module AI
|
|
73
89
|
else
|
74
90
|
text_and_images_array.push(
|
75
91
|
{
|
76
|
-
type: "
|
77
|
-
image_url:
|
78
|
-
url: process_image(image)
|
79
|
-
}
|
92
|
+
type: "input_image",
|
93
|
+
image_url: process_image(image)
|
80
94
|
}
|
81
95
|
)
|
82
96
|
end
|
@@ -100,35 +114,85 @@ module AI
|
|
100
114
|
"content-type" => "application/json"
|
101
115
|
}
|
102
116
|
|
103
|
-
response_format = if schema.nil?
|
104
|
-
{
|
105
|
-
"type" => "text"
|
106
|
-
}
|
107
|
-
else
|
108
|
-
{
|
109
|
-
"type" => "json_schema",
|
110
|
-
"json_schema" => JSON.parse(schema)
|
111
|
-
}
|
112
|
-
end
|
113
|
-
|
114
117
|
request_body_hash = {
|
115
118
|
"model" => model,
|
116
|
-
"
|
117
|
-
"messages" => messages
|
119
|
+
"input" => messages
|
118
120
|
}
|
119
121
|
|
122
|
+
# Add reasoning parameter if specified
|
123
|
+
if !@reasoning_effort.nil?
|
124
|
+
# Convert symbol back to string for the API request
|
125
|
+
request_body_hash["reasoning"] = {
|
126
|
+
"effort" => @reasoning_effort.to_s
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
130
|
+
# Handle structured output (JSON schema)
|
131
|
+
if !schema.nil?
|
132
|
+
# Parse the schema and use it with Structured Output (json_schema)
|
133
|
+
schema_obj = JSON.parse(schema)
|
134
|
+
|
135
|
+
# Extract schema name from the parsed schema, or use a default
|
136
|
+
schema_name = schema_obj["name"] || "output_object"
|
137
|
+
|
138
|
+
# Responses API uses proper Structured Output with schema
|
139
|
+
request_body_hash["text"] = {
|
140
|
+
"format" => {
|
141
|
+
"type" => "json_schema",
|
142
|
+
"schema" => schema_obj["schema"] || schema_obj,
|
143
|
+
"name" => schema_name,
|
144
|
+
"strict" => true
|
145
|
+
}
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
120
149
|
request_body_json = JSON.generate(request_body_hash)
|
121
150
|
|
122
|
-
uri = URI("https://api.openai.com/v1/
|
151
|
+
uri = URI("https://api.openai.com/v1/responses")
|
123
152
|
raw_response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
124
153
|
request = Net::HTTP::Post.new(uri, request_headers_hash)
|
125
154
|
request.body = request_body_json
|
126
155
|
http.request(request)
|
127
156
|
end
|
128
157
|
|
129
|
-
|
158
|
+
# Handle empty responses or HTTP errors
|
159
|
+
if raw_response.code.to_i >= 400
|
160
|
+
raise "HTTP Error #{raw_response.code}: #{raw_response.message}\n#{raw_response.body}"
|
161
|
+
end
|
162
|
+
|
163
|
+
if raw_response.body.nil? || raw_response.body.empty?
|
164
|
+
raise "Empty response received from OpenAI API"
|
165
|
+
end
|
130
166
|
|
131
|
-
|
167
|
+
parsed_response = JSON.parse(raw_response.body)
|
168
|
+
|
169
|
+
# Check for API errors
|
170
|
+
if parsed_response.key?("error") && parsed_response["error"].is_a?(Hash)
|
171
|
+
error_message = parsed_response["error"]["message"] || parsed_response["error"].inspect
|
172
|
+
raise "OpenAI API Error: #{error_message}"
|
173
|
+
end
|
174
|
+
|
175
|
+
# Extract the text content from the response
|
176
|
+
content = ""
|
177
|
+
|
178
|
+
# Parse response according to the documented structure
|
179
|
+
if parsed_response.key?("output") && parsed_response["output"].is_a?(Array) && !parsed_response["output"].empty?
|
180
|
+
output_item = parsed_response["output"][0]
|
181
|
+
|
182
|
+
if output_item["type"] == "message" && output_item.key?("content")
|
183
|
+
content_items = output_item["content"]
|
184
|
+
output_text_item = content_items.find { |item| item["type"] == "output_text" }
|
185
|
+
|
186
|
+
if output_text_item && output_text_item.key?("text")
|
187
|
+
content = output_text_item["text"]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# If no content is found, throw an error
|
193
|
+
if content.empty?
|
194
|
+
raise "Failed to extract content from response: #{parsed_response.inspect}"
|
195
|
+
end
|
132
196
|
|
133
197
|
messages.push({role: "assistant", content: content})
|
134
198
|
|
@@ -136,7 +200,7 @@ module AI
|
|
136
200
|
end
|
137
201
|
|
138
202
|
def inspect
|
139
|
-
"#<#{self.class.name} @messages=#{messages.inspect} @model=#{@model.inspect} @schema=#{@schema.inspect}>"
|
203
|
+
"#<#{self.class.name} @messages=#{messages.inspect} @model=#{@model.inspect} @schema=#{@schema.inspect} @reasoning_effort=#{@reasoning_effort.inspect}>"
|
140
204
|
end
|
141
205
|
|
142
206
|
private
|
@@ -56,11 +56,11 @@ z.user("1 slice of pizza")
|
|
56
56
|
response = z.assistant!
|
57
57
|
puts "Nutrition values: #{response.inspect}"
|
58
58
|
|
59
|
-
# Test with
|
60
|
-
puts "\
|
61
|
-
puts "
|
59
|
+
# Test with a single image
|
60
|
+
puts "\nSingle Image Support Test:"
|
61
|
+
puts "------------------------"
|
62
62
|
begin
|
63
|
-
img_path = File.expand_path("../../spec/fixtures/
|
63
|
+
img_path = File.expand_path("../../spec/fixtures/test1.jpg", __FILE__)
|
64
64
|
if File.exist?(img_path)
|
65
65
|
i = AI::Chat.new
|
66
66
|
i.user("What's in this image?", image: img_path)
|
@@ -70,8 +70,27 @@ begin
|
|
70
70
|
puts "Test image not found at #{img_path}"
|
71
71
|
end
|
72
72
|
rescue => e
|
73
|
-
puts "
|
74
|
-
|
73
|
+
puts "Single image test error: #{e.message}"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Test with multiple images
|
77
|
+
puts "\nMultiple Images Support Test:"
|
78
|
+
puts "--------------------------"
|
79
|
+
begin
|
80
|
+
img_path1 = File.expand_path("../../spec/fixtures/test1.jpg", __FILE__)
|
81
|
+
img_path2 = File.expand_path("../../spec/fixtures/test2.jpg", __FILE__)
|
82
|
+
img_path3 = File.expand_path("../../spec/fixtures/test3.jpg", __FILE__)
|
83
|
+
|
84
|
+
if File.exist?(img_path1) && File.exist?(img_path2) && File.exist?(img_path3)
|
85
|
+
i = AI::Chat.new
|
86
|
+
i.user("Compare these images and tell me what you see.", images: [img_path1, img_path2, img_path3])
|
87
|
+
response = i.assistant!
|
88
|
+
puts "Multiple images description: #{response}"
|
89
|
+
else
|
90
|
+
puts "One or more test images not found"
|
91
|
+
end
|
92
|
+
rescue => e
|
93
|
+
puts "Multiple images test error: #{e.message}"
|
75
94
|
end
|
76
95
|
|
77
96
|
# Get messages example
|
@@ -93,4 +112,46 @@ a.user("Tell me a joke.")
|
|
93
112
|
response = a.assistant!
|
94
113
|
puts "Assistant response after manual message: #{response}"
|
95
114
|
|
115
|
+
# Reasoning Effort Test
|
116
|
+
puts "\nReasoning Effort Test:"
|
117
|
+
puts "---------------------"
|
118
|
+
begin
|
119
|
+
r = AI::Chat.new
|
120
|
+
r.model = "o4-mini" # Use a reasoning model
|
121
|
+
r.reasoning_effort = "medium"
|
122
|
+
r.user("Write a short bash script that counts the number of unique words in a text file.")
|
123
|
+
response = r.assistant!
|
124
|
+
puts "Response with reasoning effort 'medium': #{response}"
|
125
|
+
rescue => e
|
126
|
+
puts "Reasoning effort test error: #{e.message}"
|
127
|
+
end
|
128
|
+
|
129
|
+
# Reasoning Effort Validation Test
|
130
|
+
puts "\nReasoning Effort Validation Test:"
|
131
|
+
puts "-------------------------------"
|
132
|
+
begin
|
133
|
+
r = AI::Chat.new
|
134
|
+
puts "Setting valid reasoning effort string 'low'..."
|
135
|
+
r.reasoning_effort = "low"
|
136
|
+
puts "Success: reasoning_effort = #{r.reasoning_effort}"
|
137
|
+
|
138
|
+
puts "Setting valid reasoning effort symbol :medium..."
|
139
|
+
r.reasoning_effort = :medium
|
140
|
+
puts "Success: reasoning_effort = #{r.reasoning_effort}"
|
141
|
+
|
142
|
+
puts "Setting valid reasoning effort string 'high'..."
|
143
|
+
r.reasoning_effort = "high"
|
144
|
+
puts "Success: reasoning_effort = #{r.reasoning_effort}"
|
145
|
+
|
146
|
+
puts "Setting nil reasoning effort..."
|
147
|
+
r.reasoning_effort = nil
|
148
|
+
puts "Success: reasoning_effort = #{r.reasoning_effort}"
|
149
|
+
|
150
|
+
puts "Setting invalid reasoning effort 'extreme'..."
|
151
|
+
r.reasoning_effort = "extreme"
|
152
|
+
puts "This line should not be reached"
|
153
|
+
rescue ArgumentError => e
|
154
|
+
puts "Expected error caught: #{e.message}"
|
155
|
+
end
|
156
|
+
|
96
157
|
puts "\nTests completed!"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ai-chat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Raghu Betina
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: base64
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,8 +123,8 @@ dependencies:
|
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '1.32'
|
111
125
|
description: This gem provides a class called `AI::Chat` that is intended to make
|
112
|
-
it as easy as possible to use OpenAI's
|
113
|
-
|
126
|
+
it as easy as possible to use OpenAI's Responses API. Supports Structured Output
|
127
|
+
and Image Processing.
|
114
128
|
email:
|
115
129
|
- raghu@firstdraft.com
|
116
130
|
- jelani@firstdraft.com
|
@@ -120,7 +134,6 @@ extra_rdoc_files: []
|
|
120
134
|
files:
|
121
135
|
- ".config/rubocop/config.yml"
|
122
136
|
- ".reek.yml"
|
123
|
-
- ".rspec_status"
|
124
137
|
- ".ruby-version"
|
125
138
|
- CHANGELOG.md
|
126
139
|
- CODE_OF_CONDUCT.md
|
@@ -128,7 +141,6 @@ files:
|
|
128
141
|
- LICENSE.txt
|
129
142
|
- README.md
|
130
143
|
- Rakefile
|
131
|
-
- ai_chat.gemspec
|
132
144
|
- lib/ai-chat.rb
|
133
145
|
- lib/ai/chat.rb
|
134
146
|
- lib/ai/chat/version.rb
|
@@ -158,5 +170,5 @@ requirements: []
|
|
158
170
|
rubygems_version: 3.6.5
|
159
171
|
specification_version: 4
|
160
172
|
summary: This gem provides a class called `AI::Chat` that is intended to make it as
|
161
|
-
easy as possible to use OpenAI's
|
173
|
+
easy as possible to use OpenAI's Responses API.
|
162
174
|
test_files: []
|
data/.rspec_status
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
example_id | status | run_time |
|
2
|
-
--------------------------------------------- | ------ | --------------- |
|
3
|
-
./spec/ai/chat/image_support_spec.rb[1:1:1:1] | passed | 0.00007 seconds |
|
4
|
-
./spec/ai/chat/image_support_spec.rb[1:1:2:1] | passed | 0.0001 seconds |
|
5
|
-
./spec/ai/chat/image_support_spec.rb[1:1:3:1] | passed | 0.00012 seconds |
|
6
|
-
./spec/ai/chat/image_support_spec.rb[1:1:3:2] | passed | 0.00018 seconds |
|
7
|
-
./spec/ai/chat/image_support_spec.rb[1:2:1:1] | passed | 0.0016 seconds |
|
8
|
-
./spec/ai/chat/image_support_spec.rb[1:2:1:2] | passed | 0.0001 seconds |
|
9
|
-
./spec/ai/chat/image_support_spec.rb[1:2:2:1] | passed | 0.00011 seconds |
|
10
|
-
./spec/ai/chat/image_support_spec.rb[1:2:3:1] | passed | 0.00007 seconds |
|
11
|
-
./spec/ai/chat/image_support_spec.rb[1:2:3:2] | passed | 0.00013 seconds |
|
12
|
-
./spec/ai/chat/image_support_spec.rb[1:3:1] | passed | 0.00005 seconds |
|
13
|
-
./spec/ai/chat/image_support_spec.rb[1:3:2] | passed | 0.00006 seconds |
|
14
|
-
./spec/ai/chat/image_support_spec.rb[1:3:3] | passed | 0.00008 seconds |
|
15
|
-
./spec/ai/chat/image_support_spec.rb[1:3:4] | passed | 0.00017 seconds |
|
16
|
-
./spec/ai/chat/image_support_spec.rb[1:3:5] | passed | 0.00074 seconds |
|
data/ai_chat.gemspec
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "lib/ai/chat/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = "ai-chat"
|
7
|
-
spec.version = AI::Chat::VERSION
|
8
|
-
spec.authors = ["Raghu Betina", "Jelani Woods"]
|
9
|
-
spec.email = ["raghu@firstdraft.com", "jelani@firstdraft.com"]
|
10
|
-
|
11
|
-
spec.summary = "This gem provides a class called `AI::Chat` that is intended to make it as easy as possible to use OpenAI's Chat Completions endpoint."
|
12
|
-
spec.description = "This gem provides a class called `AI::Chat` that is intended to make it as easy as possible to use OpenAI's Chat Completions endpoint. Supports Structured Output."
|
13
|
-
spec.homepage = "https://github.com/firstdraft/ai-chat"
|
14
|
-
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = ">= 2.0.0"
|
16
|
-
|
17
|
-
# spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
18
|
-
|
19
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
20
|
-
spec.metadata["source_code_uri"] = "https://github.com/firstdraft/ai-chat"
|
21
|
-
spec.metadata["changelog_uri"] = "https://github.com/firstdraft/ai-chat/blob/main/CHANGELOG.md"
|
22
|
-
|
23
|
-
# Specify which files should be added to the gem when it is released.
|
24
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
-
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
|
-
`git ls-files -z`.split("\x0").reject do |f|
|
27
|
-
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(git|travis|circleci)|appveyor)})
|
28
|
-
end
|
29
|
-
end
|
30
|
-
spec.bindir = "exe"
|
31
|
-
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
32
|
-
spec.require_paths = ["lib"]
|
33
|
-
|
34
|
-
# Register dependencies of the gem
|
35
|
-
spec.add_runtime_dependency "mime-types", "~> 3.0"
|
36
|
-
|
37
|
-
# Development dependencies
|
38
|
-
spec.add_development_dependency "rake", "~> 13.0"
|
39
|
-
spec.add_development_dependency "rspec", "~> 3.12"
|
40
|
-
spec.add_development_dependency "factory_bot", "~> 6.2"
|
41
|
-
spec.add_development_dependency "webmock", "~> 3.18"
|
42
|
-
spec.add_development_dependency "vcr", "~> 6.1"
|
43
|
-
spec.add_development_dependency "standard", "~> 1.32"
|
44
|
-
|
45
|
-
# For more information and examples about making a new gem, check out our
|
46
|
-
# guide at: https://bundler.io/guides/creating_gem.html
|
47
|
-
end
|