rager 0.2.1 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32cd931dd6c3c714456232f7aeb15743580a605330051a31c4167a0435e8d766
4
- data.tar.gz: bd28897b484c9b6d0972b229b6fe834eb532b1027baf855b33ac9940df303c8a
3
+ metadata.gz: 5e1955c552055b99969da67b3e85df748ee3077b5f02c8dc46fe418801acbc24
4
+ data.tar.gz: 5bba65ff81cda2e4dc48711973107402379255e36d80e421d85951694df6edea
5
5
  SHA512:
6
- metadata.gz: 9b98958d909a001eb2f21a65e1186a473fa5c11e1e86255e0d9c9cfdd535b3ce6131c90c1fa9b5665fe4831f168860d49e399b9b25d0bcd179b2a022e9db8d7a
7
- data.tar.gz: 70d77abac363b663d6b82636b93af19bddf02f37570599e6df71e6a2f0f30fbb309d87b2f8431bdf4106bf9e3559448579b66ac8cd2cb34eca2b3ccca0f98bbe
6
+ metadata.gz: 671cc3bc70834f3c5b476dad2dc8b6cd0413f0ec2269c7cc7a75d01244f4f511f3dcf18b6b1a208653e0dd0ee67af6ce0082603173564a103722b284e2da5c43
7
+ data.tar.gz: f945dd32c95854d2fe6febe850e619bc8a5c4a65b75c67a0e38e9a36219e48cf6b09a55265d9cdb499d2dbfabed8c2dfd356c836eaa88f65d7fe8747dc980bb2
data/README.md CHANGED
@@ -18,7 +18,7 @@ bundle add rager
18
18
  Otherwise you can add it to your Gemfile directly:
19
19
 
20
20
  ```Ruby
21
- gem "rager", "~> 0.2.0"
21
+ gem "rager", "~> 0.3.0"
22
22
  ```
23
23
 
24
24
  ## License
@@ -22,63 +22,50 @@ module Rager
22
22
  api_key = options.api_key || ENV["OPENAI_API_KEY"]
23
23
  raise Rager::Errors::MissingCredentialsError.new("OpenAI", "OPENAI_API_KEY") if api_key.nil?
24
24
 
25
- url = options.url || ENV["OPENAI_URL"] || "https://api.openai.com/v1/chat/completions"
26
- model = options.model || "gpt-4.1"
27
-
28
- openai_messages = build_openai_messages(messages, options.history, options.system_prompt)
29
-
30
- headers = {
31
- "Content-Type" => "application/json"
32
- }
33
- headers["Authorization"] = "Bearer #{api_key}" if api_key
34
-
35
25
  body = {
36
- model: model,
37
- messages: openai_messages
38
- }
39
- body[:temperature] = options.temperature unless options.temperature.nil?
40
- body[:n] = options.n unless options.n.nil?
41
- body[:stream] = options.stream unless options.stream.nil?
42
- body[:seed] = options.seed unless options.seed.nil?
43
-
44
- if options.schema && options.schema_name
45
- body[:response_format] = {
46
- type: "json_schema",
47
- json_schema: {
48
- name: T.must(options.schema_name).downcase,
49
- strict: true,
50
- schema: Rager::Chat::Schema.dry_schema_to_json_schema(T.must(options.schema))
26
+ model: options.model || "gpt-4.1",
27
+ messages: build_openai_messages(messages, options.history, options.system_prompt)
28
+ }.tap do |b|
29
+ b[:temperature] = options.temperature if options.temperature
30
+ b[:n] = options.n if options.n
31
+ b[:stream] = options.stream if options.stream
32
+ b[:seed] = options.seed if options.seed
33
+
34
+ if options.schema && options.schema_name
35
+ b[:response_format] = {
36
+ type: "json_schema",
37
+ json_schema: {
38
+ name: T.must(options.schema_name).downcase,
39
+ strict: true,
40
+ schema: Rager::Chat::Schema.dry_schema_to_json_schema(T.must(options.schema))
41
+ }
51
42
  }
52
- }
43
+ end
53
44
  end
54
45
 
46
+ headers = {"Content-Type" => "application/json"}
47
+ headers["Authorization"] = "Bearer #{api_key}" if api_key
48
+
55
49
  request = Rager::Http::Request.new(
56
50
  verb: Rager::Http::Verb::Post,
57
- url: url,
51
+ url: options.url || ENV["OPENAI_URL"] || "https://api.openai.com/v1/chat/completions",
58
52
  headers: headers,
59
53
  body: body.to_json
60
54
  )
61
55
 
62
- http_adapter = Rager.config.http_adapter
63
- response = http_adapter.make_request(request)
56
+ response = Rager.config.http_adapter.make_request(request)
64
57
  response_body = T.must(response.body)
65
58
 
66
- if response.status != 200
67
- raise Rager::Errors::HttpError.new(
68
- http_adapter,
69
- response.status,
70
- T.cast(response_body, String)
71
- )
72
- end
59
+ raise Rager::Errors::HttpError.new(Rager.config.http_adapter, response.status, T.cast(response_body, String)) if response.status != 200
73
60
 
74
61
  case response_body
75
- when String
76
- parse_non_stream_body(response_body)
77
- when Enumerator
78
- create_message_delta_stream(response_body)
62
+ when String then handle_non_stream_body(response_body)
63
+ when Enumerator then handle_stream_body(response_body)
79
64
  end
80
65
  end
81
66
 
67
+ private
68
+
82
69
  sig do
83
70
  params(
84
71
  messages: T::Array[Rager::Chat::Message],
@@ -90,94 +77,75 @@ module Rager
90
77
  result = T.let([], OpenaiMessages)
91
78
 
92
79
  if history.empty? && system_prompt && !system_prompt.empty?
93
- result << {"role" => "system",
94
- "content" => system_prompt}
80
+ result << {"role" => "system", "content" => system_prompt}
95
81
  end
96
82
 
97
- history.each do |msg|
98
- role_str = msg.role.is_a?(String) ? msg.role : msg.role.serialize
99
- result << {"role" => role_str, "content" => msg.content}
100
- end
101
-
102
- messages.each do |message|
103
- role_str = message.role.is_a?(String) ? message.role : message.role.serialize
83
+ (history + messages).each do |message|
84
+ role = message.role.is_a?(String) ? message.role : message.role.serialize
104
85
  content = message.content
105
86
 
106
- if content.is_a?(String)
107
- result << {"role" => role_str, "content" => content}
108
- elsif content.is_a?(Array)
109
- formatted_content = content.map do |item|
110
- item_type = item.type
111
- case item_type
112
- when Rager::Chat::MessageContentType::Text
113
- {"type" => "text", "text" => item.content}
114
- when Rager::Chat::MessageContentType::ImageUrl
115
- {"type" => "image_url", "image_url" => {"url" => item.content}}
116
- when Rager::Chat::MessageContentType::ImageBase64
117
- image_type = T.must(item.image_type)
118
- image_mime_type = case image_type
119
- when Rager::Chat::MessageContentImageType::Jpeg then "image/jpeg"
120
- when Rager::Chat::MessageContentImageType::Png then "image/png"
121
- when Rager::Chat::MessageContentImageType::Webp then "image/webp"
122
- end
123
- data_uri = "data:#{image_mime_type};base64,#{item.content}"
124
- {"type" => "image_url", "image_url" => {"url" => data_uri}}
125
- end
126
- end
127
- result << {"role" => role_str, "content" => formatted_content}
87
+ case content
88
+ when String
89
+ result << {"role" => role, "content" => content}
90
+ when Array
91
+ formatted_content = content.map { |item| format_content_item(item) }
92
+ result << {"role" => role, "content" => formatted_content}
128
93
  end
129
94
  end
130
95
 
131
96
  result
132
97
  end
133
98
 
134
- sig { params(body: String).returns(T::Array[String]) }
135
- def parse_non_stream_body(body)
136
- messages = T.let([], T::Array[String])
137
-
138
- begin
139
- response_data = JSON.parse(body)
140
- if response_data.key?("choices") && response_data["choices"].is_a?(Array)
141
- response_data["choices"].each do |choice|
142
- text = choice.dig("message", "content").to_s
143
- messages << text unless text.empty?
144
- end
99
+ sig { params(item: Rager::Chat::MessageContent).returns(T::Hash[String, T.untyped]) }
100
+ def format_content_item(item)
101
+ case item.type
102
+ when Rager::Chat::MessageContentType::Text
103
+ {"type" => "text", "text" => item.content}
104
+ when Rager::Chat::MessageContentType::ImageUrl
105
+ {"type" => "image_url", "image_url" => {"url" => item.content}}
106
+ when Rager::Chat::MessageContentType::ImageBase64
107
+ mime_type = case T.must(item.image_type)
108
+ when Rager::Chat::MessageContentImageType::Jpeg then "image/jpeg"
109
+ when Rager::Chat::MessageContentImageType::Png then "image/png"
110
+ when Rager::Chat::MessageContentImageType::Webp then "image/webp"
145
111
  end
146
- rescue JSON::ParserError
147
- raise Rager::Errors::ParseError.new(
148
- "OpenAI response body is not valid JSON",
149
- body
150
- )
112
+ {"type" => "image_url", "image_url" => {"url" => "data:#{mime_type};base64,#{item.content}"}}
151
113
  end
114
+ end
152
115
 
153
- messages
116
+ sig { params(body: String).returns(T::Array[String]) }
117
+ def handle_non_stream_body(body)
118
+ response_data = JSON.parse(body)
119
+ return [] unless response_data.key?("choices") && response_data["choices"].is_a?(Array)
120
+
121
+ response_data["choices"].filter_map do |choice|
122
+ text = choice.dig("message", "content").to_s
123
+ text unless text.empty?
124
+ end
125
+ rescue JSON::ParserError
126
+ raise Rager::Errors::ParseError.new("OpenAI response body is not valid JSON", body)
154
127
  end
155
128
 
156
129
  sig { params(body: T::Enumerator[String]).returns(T::Enumerator[Rager::Chat::MessageDelta]) }
157
- def create_message_delta_stream(body)
130
+ def handle_stream_body(body)
158
131
  Enumerator.new do |yielder|
159
132
  buffer = +""
160
133
 
161
- process_chunk = lambda do |chunk|
134
+ process_chunk = ->(chunk) do
162
135
  buffer << chunk
163
- pattern = /\Adata: (.*?)\n\n|\Adata: (.*?)\n/
164
- while (event_match = buffer.match(pattern))
165
- full_event = T.must(event_match[0])
166
- data_line = event_match[1] || event_match[2]
167
-
168
- buffer.delete_prefix!(full_event)
136
+ while (match = buffer.match(/\Adata: (.*?)\n\n|\Adata: (.*?)\n/))
137
+ buffer.delete_prefix!(T.must(match[0]))
138
+ data_line = match[1] || match[2]
169
139
 
170
- next if data_line.nil? || data_line.strip.empty?
171
- next if data_line.strip == "[DONE]"
140
+ next if data_line.nil? || data_line.strip.empty? || data_line.strip == "[DONE]"
172
141
 
173
142
  begin
174
143
  data = JSON.parse(data_line)
175
- if data.key?("choices") && data["choices"].is_a?(Array)
176
- data["choices"].each do |choice|
177
- choice_index = choice.dig("index") || 0
178
- delta = choice.dig("delta", "content")
179
- yielder << Rager::Chat::MessageDelta.new(index: choice_index, content: delta) if delta
180
- end
144
+ next unless data.key?("choices") && data["choices"].is_a?(Array)
145
+
146
+ data["choices"].each do |choice|
147
+ delta = choice.dig("delta", "content")
148
+ yielder << Rager::Chat::MessageDelta.new(index: choice.dig("index") || 0, content: delta) if delta
181
149
  end
182
150
  rescue JSON::ParserError
183
151
  next
@@ -186,7 +154,6 @@ module Rager
186
154
  end
187
155
 
188
156
  body.each(&process_chunk)
189
-
190
157
  process_chunk.call("\n") unless buffer.empty?
191
158
  end
192
159
  end
data/lib/rager/chat.rb CHANGED
@@ -9,7 +9,7 @@ module Rager
9
9
 
10
10
  sig do
11
11
  params(
12
- messages: T::Array[Rager::Chat::Message],
12
+ messages: Rager::Types::ChatInput,
13
13
  options: Rager::Chat::Options
14
14
  ).returns(Rager::Types::ChatOutput)
15
15
  end
data/lib/rager/config.rb CHANGED
@@ -11,6 +11,9 @@ module Rager
11
11
  attr_accessor :http_adapter
12
12
 
13
13
  sig { returns(T.nilable(Rager::Logger)) }
14
+ attr_accessor :logger_type
15
+
16
+ sig { returns(::Logger) }
14
17
  attr_accessor :logger
15
18
 
16
19
  sig { returns(T.nilable(String)) }
@@ -22,7 +25,8 @@ module Rager
22
25
  sig { void }
23
26
  def initialize
24
27
  @http_adapter = T.let(Rager::Http::Adapters::AsyncHttp.new, Rager::Http::Adapters::Abstract)
25
- @logger = T.let(nil, T.nilable(Rager::Logger))
28
+ @logger_type = T.let(nil, T.nilable(Rager::Logger))
29
+ @logger = T.let(::Logger.new($stdout), ::Logger)
26
30
  @url = T.let(nil, T.nilable(String))
27
31
  @api_key = T.let(nil, T.nilable(String))
28
32
  end
data/lib/rager/context.rb CHANGED
@@ -22,7 +22,7 @@ module Rager
22
22
 
23
23
  sig do
24
24
  params(
25
- messages: T.any(String, T::Array[Rager::Chat::Message]),
25
+ messages: T.any(String, Rager::Types::ChatInput),
26
26
  kwargs: T.untyped
27
27
  ).returns(Rager::Result)
28
28
  end
@@ -46,7 +46,7 @@ module Rager
46
46
 
47
47
  sig do
48
48
  params(
49
- text: T.any(String, T::Array[String]),
49
+ text: T.any(String, Rager::Types::EmbedInput),
50
50
  kwargs: T.untyped
51
51
  ).returns(Rager::Result)
52
52
  end
@@ -65,7 +65,7 @@ module Rager
65
65
 
66
66
  sig do
67
67
  params(
68
- prompt: String,
68
+ prompt: Rager::Types::ImageGenInput,
69
69
  kwargs: T.untyped
70
70
  ).returns(Rager::Result)
71
71
  end
@@ -80,7 +80,7 @@ module Rager
80
80
 
81
81
  sig do
82
82
  params(
83
- prompt: String,
83
+ prompt: Rager::Types::MeshGenInput,
84
84
  kwargs: T.untyped
85
85
  ).returns(Rager::Result)
86
86
  end
@@ -95,7 +95,7 @@ module Rager
95
95
 
96
96
  sig do
97
97
  params(
98
- query: Rager::Rerank::Query,
98
+ query: Rager::Types::RerankInput,
99
99
  kwargs: T.untyped
100
100
  ).returns(Rager::Result)
101
101
  end
@@ -110,7 +110,7 @@ module Rager
110
110
 
111
111
  sig do
112
112
  params(
113
- query: String,
113
+ query: Rager::Types::SearchInput,
114
114
  kwargs: T.untyped
115
115
  ).returns(Rager::Result)
116
116
  end
@@ -125,7 +125,7 @@ module Rager
125
125
 
126
126
  sig do
127
127
  params(
128
- input: Rager::Template::Input,
128
+ input: Rager::Types::TemplateInput,
129
129
  kwargs: T.untyped
130
130
  ).returns(Rager::Result)
131
131
  end
@@ -150,27 +150,47 @@ module Rager
150
150
  ).returns(Rager::Result)
151
151
  end
152
152
  def execute(operation, options_struct, kwargs, input, &block)
153
- input_ids = kwargs.delete(:input_ids)
153
+ name = kwargs.delete(:name)
154
+ iids = kwargs.delete(:iids)
154
155
 
155
156
  options = options_struct.new(**kwargs)
156
157
  options.validate
157
158
 
158
159
  start_time = Time.now
159
160
 
160
- output = yield(options)
161
-
162
- Result.new(
163
- id: @id,
164
- context_id: @id,
165
- hash: @hash,
166
- operation: operation,
167
- input: input,
168
- options: options,
169
- start_time: start_time.to_i,
170
- end_time: Time.now.to_i,
171
- output: output,
172
- input_ids: input_ids
173
- ).tap(&:log)
161
+ begin
162
+ output = yield(options)
163
+
164
+ Result.new(
165
+ id: @id,
166
+ context_id: @id,
167
+ operation: operation,
168
+ input: input,
169
+ output: output,
170
+ options: options,
171
+ start_time: start_time.to_i,
172
+ end_time: Time.now.to_i,
173
+ name: name,
174
+ iids: iids,
175
+ error: nil
176
+ ).tap(&:log)
177
+ rescue => e
178
+ Result.new(
179
+ id: @id,
180
+ context_id: @id,
181
+ operation: operation,
182
+ input: input,
183
+ output: nil,
184
+ options: options,
185
+ start_time: start_time.to_i,
186
+ end_time: Time.now.to_i,
187
+ name: name,
188
+ iids: iids,
189
+ error: e.message
190
+ ).tap(&:log)
191
+
192
+ raise e
193
+ end
174
194
  end
175
195
 
176
196
  sig { returns(T.nilable(String)) }
@@ -14,17 +14,6 @@ module Rager
14
14
  const :model, T.nilable(String)
15
15
  const :api_key, T.nilable(String)
16
16
  const :seed, T.nilable(Integer)
17
-
18
- sig { override.returns(T::Hash[String, T.untyped]) }
19
- def serialize_safe
20
- result = serialize
21
- result["api_key"] = "[REDACTED]" if result.key?("api_key")
22
- result
23
- end
24
-
25
- sig { override.void }
26
- def validate
27
- end
28
17
  end
29
18
  end
30
19
  end
@@ -20,37 +20,25 @@ module Rager
20
20
  api_key = options.api_key || ENV["OPENAI_API_KEY"]
21
21
  raise Rager::Errors::MissingCredentialsError.new("OpenAI", "OPENAI_API_KEY") if api_key.nil?
22
22
 
23
- url = options.url || ENV["OPENAI_URL"] || "https://api.openai.com/v1/embeddings"
24
- model = options.model || "text-embedding-3-large"
25
-
26
- headers = {
27
- "Content-Type" => "application/json"
28
- }
23
+ headers = {"Content-Type" => "application/json"}
29
24
  headers["Authorization"] = "Bearer #{api_key}" if api_key
30
25
 
31
26
  body = {
32
- model: model,
27
+ model: options.model || "text-embedding-3-large",
33
28
  input: text
34
29
  }
35
30
 
36
31
  request = Rager::Http::Request.new(
37
32
  verb: Rager::Http::Verb::Post,
38
- url: url,
33
+ url: options.url || ENV["OPENAI_URL"] || "https://api.openai.com/v1/embeddings",
39
34
  headers: headers,
40
35
  body: body.to_json
41
36
  )
42
37
 
43
- http_adapter = Rager.config.http_adapter
44
- response = http_adapter.make_request(request)
38
+ response = Rager.config.http_adapter.make_request(request)
45
39
  response_body = T.cast(T.must(response.body), String)
46
40
 
47
- if response.status != 200
48
- raise Rager::Errors::HttpError.new(
49
- http_adapter,
50
- response.status,
51
- response_body
52
- )
53
- end
41
+ raise Rager::Errors::HttpError.new(Rager.config.http_adapter, response.status, response_body) if response.status != 200
54
42
 
55
43
  parsed_response = JSON.parse(response_body)
56
44
  parsed_response["data"].map { |item| item["embedding"] }
data/lib/rager/embed.rb CHANGED
@@ -9,7 +9,7 @@ module Rager
9
9
 
10
10
  sig do
11
11
  params(
12
- text: T::Array[String],
12
+ text: Rager::Types::EmbedInput,
13
13
  options: Rager::Embed::Options
14
14
  ).returns(Rager::Types::EmbedOutput)
15
15
  end
@@ -10,8 +10,8 @@ module Rager
10
10
 
11
11
  sig { params(adapter: Rager::Http::Adapters::Abstract, status: Integer, body: T.nilable(String)).void }
12
12
  def initialize(adapter, status, body)
13
- message = "HTTP Error #{status} using adapter #{adapter.class.name}"
14
- message += " -- #{body}" if body
13
+ message = "HTTP Error #{status} using #{adapter.class.name}"
14
+ message += ": #{body}" if body
15
15
  super(message)
16
16
  end
17
17
  end
@@ -11,7 +11,7 @@ module Rager
11
11
  sig { params(invalid_keys: T::Array[String], description: T.nilable(String)).void }
12
12
  def initialize(invalid_keys:, description: nil)
13
13
  message = "Invalid keys #{invalid_keys.join(", ")}"
14
- message += " -- #{description})" if description
14
+ message += " (#{description})" if description
15
15
  super(message)
16
16
  end
17
17
  end
@@ -6,9 +6,16 @@ require "sorbet-runtime"
6
6
  module Rager
7
7
  module Http
8
8
  class Response < T::Struct
9
+ extend T::Sig
10
+
9
11
  const :status, Integer
10
12
  const :headers, T::Hash[String, T.any(String, T::Array[String])]
11
13
  const :body, T.nilable(T.any(String, T::Enumerator[String]))
14
+
15
+ sig { returns(T::Boolean) }
16
+ def success?
17
+ status >= 200 && status < 300
18
+ end
12
19
  end
13
20
  end
14
21
  end
@@ -11,19 +11,9 @@ module Rager
11
11
 
12
12
  const :provider, String, default: "replicate"
13
13
  const :model, String, default: "black-forest-labs/flux-schnell"
14
+ const :output_format, T.nilable(Rager::ImageGen::OutputFormat)
14
15
  const :api_key, T.nilable(String)
15
16
  const :seed, T.nilable(Integer)
16
-
17
- sig { override.returns(T::Hash[String, T.untyped]) }
18
- def serialize_safe
19
- result = serialize
20
- result["api_key"] = "[REDACTED]" if result.key?("api_key")
21
- result
22
- end
23
-
24
- sig { override.void }
25
- def validate
26
- end
27
17
  end
28
18
  end
29
19
  end
@@ -0,0 +1,18 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+
6
+ module Rager
7
+ module ImageGen
8
+ class OutputFormat < T::Enum
9
+ extend T::Sig
10
+
11
+ enums do
12
+ Png = new("png")
13
+ Jpg = new("jpg")
14
+ Webp = new("webp")
15
+ end
16
+ end
17
+ end
18
+ end
@@ -12,42 +12,38 @@ module Rager
12
12
 
13
13
  sig { override.params(prompt: String, options: Rager::ImageGen::Options).returns(Rager::Types::ImageGenOutput) }
14
14
  def image_gen(prompt, options)
15
- url = "https://api.replicate.com/v1/models/#{options.model}/predictions"
16
15
  api_key = options.api_key || ENV["REPLICATE_API_KEY"]
17
16
  raise Rager::Errors::MissingCredentialsError.new("Replicate", "REPLICATE_API_KEY") if api_key.nil?
18
17
 
19
- headers = {
20
- "Authorization" => "Bearer #{api_key}",
21
- "Content-Type" => "application/json",
22
- "Prefer" => "wait"
23
- }
24
-
25
18
  body = {
26
19
  input: {
27
20
  prompt: prompt
28
21
  }
29
- }
30
- body[:input][:seed] = options.seed unless options.seed.nil?
22
+ }.tap do |b|
23
+ b[:input][:output_format] = T.must(options.output_format).serialize if options.output_format
24
+ b[:input][:seed] = options.seed if options.seed
25
+ end
31
26
 
32
27
  request = Rager::Http::Request.new(
33
- url: url,
28
+ url: "https://api.replicate.com/v1/models/#{options.model}/predictions",
34
29
  verb: Rager::Http::Verb::Post,
35
- headers: headers,
30
+ headers: {
31
+ "Authorization" => "Bearer #{api_key}",
32
+ "Content-Type" => "application/json",
33
+ "Prefer" => "wait"
34
+ },
36
35
  body: body.to_json
37
36
  )
38
37
 
39
- http_adapter = Rager.config.http_adapter
40
- response = http_adapter.make_request(request)
38
+ response = Rager.config.http_adapter.make_request(request)
41
39
  response_body = T.cast(T.must(response.body), String)
42
40
 
43
- raise Rager::Errors::HttpError.new(http_adapter, response.status, response_body) unless [200, 201].include?(response.status)
41
+ raise Rager::Errors::HttpError.new(Rager.config.http_adapter, response.status, response_body) unless [200, 201].include?(response.status)
44
42
 
45
- begin
46
- parsed = JSON.parse(response_body)
47
- parsed.fetch("output").first
48
- rescue JSON::ParserError, KeyError => e
49
- raise Rager::Errors::ParseError.new(e.message, response_body)
50
- end
43
+ parsed = JSON.parse(response_body)
44
+ parsed.fetch("output").first
45
+ rescue JSON::ParserError, KeyError => e
46
+ raise Rager::Errors::ParseError.new(e.message, response_body)
51
47
  end
52
48
  end
53
49
  end
@@ -9,7 +9,7 @@ module Rager
9
9
 
10
10
  sig do
11
11
  params(
12
- prompt: String,
12
+ prompt: Rager::Types::ImageGenInput,
13
13
  options: Rager::ImageGen::Options
14
14
  ).returns(Rager::Types::ImageGenOutput)
15
15
  end
@@ -14,17 +14,6 @@ module Rager
14
14
  const :version, String, default: "4876f2a8da1c544772dffa32e8889da4a1bab3a1f5c1937bfcfccb99ae347251"
15
15
  const :api_key, T.nilable(String)
16
16
  const :seed, T.nilable(Integer)
17
-
18
- sig { override.returns(T::Hash[String, T.untyped]) }
19
- def serialize_safe
20
- result = serialize
21
- result["api_key"] = "[REDACTED]" if result.key?("api_key")
22
- result
23
- end
24
-
25
- sig { override.void }
26
- def validate
27
- end
28
17
  end
29
18
  end
30
19
  end