rager 0.5.0 → 0.7.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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +49 -7
  3. data/lib/rager/chat/message.rb +10 -0
  4. data/lib/rager/chat/message_content.rb +7 -0
  5. data/lib/rager/chat/message_delta.rb +7 -0
  6. data/lib/rager/chat/options.rb +12 -9
  7. data/lib/rager/chat/providers/openai.rb +64 -48
  8. data/lib/rager/chat/schema.rb +3 -4
  9. data/lib/rager/config.rb +16 -20
  10. data/lib/rager/context.rb +326 -97
  11. data/lib/rager/context_options.rb +23 -0
  12. data/lib/rager/embed/options.rb +4 -3
  13. data/lib/rager/embed/providers/openai.rb +14 -6
  14. data/lib/rager/errors/credentials_error.rb +24 -0
  15. data/lib/rager/errors/dependency_error.rb +23 -0
  16. data/lib/rager/errors/http_error.rb +12 -5
  17. data/lib/rager/errors/options_error.rb +10 -5
  18. data/lib/rager/errors/parse_error.rb +9 -5
  19. data/lib/rager/errors/template_error.rb +10 -4
  20. data/lib/rager/errors/timeout_error.rb +25 -0
  21. data/lib/rager/http/adapters/async_http.rb +66 -14
  22. data/lib/rager/http/adapters/mock.rb +41 -45
  23. data/lib/rager/http/adapters/net_http.rb +144 -0
  24. data/lib/rager/http/request.rb +2 -0
  25. data/lib/rager/{image_gen → image}/options.rb +5 -4
  26. data/lib/rager/{image_gen → image}/output_format.rb +1 -1
  27. data/lib/rager/{image_gen → image}/providers/abstract.rb +4 -4
  28. data/lib/rager/{image_gen → image}/providers/replicate.rb +19 -14
  29. data/lib/rager/{logger.rb → log_strategy.rb} +2 -1
  30. data/lib/rager/{mesh_gen → mesh}/options.rb +4 -3
  31. data/lib/rager/{mesh_gen → mesh}/providers/abstract.rb +4 -4
  32. data/lib/rager/{mesh_gen → mesh}/providers/replicate.rb +20 -14
  33. data/lib/rager/operation.rb +2 -2
  34. data/lib/rager/options.rb +1 -1
  35. data/lib/rager/outcome.rb +25 -0
  36. data/lib/rager/providers.rb +61 -0
  37. data/lib/rager/rerank/{query.rb → input.rb} +8 -1
  38. data/lib/rager/rerank/options.rb +3 -2
  39. data/lib/rager/rerank/providers/abstract.rb +2 -2
  40. data/lib/rager/rerank/providers/cohere.rb +24 -15
  41. data/lib/rager/rerank/result.rb +8 -1
  42. data/lib/rager/result.rb +98 -108
  43. data/lib/rager/search/options.rb +4 -1
  44. data/lib/rager/search/providers/jina.rb +68 -0
  45. data/lib/rager/search/result.rb +9 -2
  46. data/lib/rager/template/input.rb +9 -0
  47. data/lib/rager/template/options.rb +1 -1
  48. data/lib/rager/template/providers/erb.rb +3 -3
  49. data/lib/rager/template/providers/mustache.rb +30 -0
  50. data/lib/rager/types.rb +28 -17
  51. data/lib/rager/utils/http.rb +92 -27
  52. data/lib/rager/utils/replicate.rb +40 -21
  53. data/lib/rager/utils/runtime.rb +21 -0
  54. data/lib/rager/version.rb +1 -1
  55. metadata +22 -36
  56. data/lib/rager/chat.rb +0 -35
  57. data/lib/rager/embed.rb +0 -35
  58. data/lib/rager/errors/missing_credentials_error.rb +0 -19
  59. data/lib/rager/errors/unknown_provider_error.rb +0 -17
  60. data/lib/rager/image_gen.rb +0 -31
  61. data/lib/rager/mesh_gen.rb +0 -31
  62. data/lib/rager/rerank.rb +0 -35
  63. data/lib/rager/search/providers/brave.rb +0 -59
  64. data/lib/rager/search.rb +0 -35
  65. data/lib/rager/template.rb +0 -35
@@ -8,11 +8,16 @@ module Rager
8
8
  class OptionsError < Rager::Error
9
9
  extend T::Sig
10
10
 
11
- sig { params(invalid_keys: T::Array[String], description: T.nilable(String)).void }
12
- def initialize(invalid_keys:, description: nil)
13
- message = "Invalid keys #{invalid_keys.join(", ")}"
14
- message += " (#{description})" if description
15
- super(message)
11
+ sig { params(options: Rager::Types::Options, invalid_keys: T::Array[String], details: T.nilable(String)).void }
12
+ def initialize(options, invalid_keys, details: nil)
13
+ error_data = {
14
+ type: "options",
15
+ options: options.serialize_safe,
16
+ invalid_keys: invalid_keys,
17
+ details: details
18
+ }
19
+
20
+ super(error_data.to_json)
16
21
  end
17
22
  end
18
23
  end
@@ -8,11 +8,15 @@ module Rager
8
8
  class ParseError < Rager::Error
9
9
  extend T::Sig
10
10
 
11
- sig { params(description: String, body: T.nilable(String)).void }
12
- def initialize(description, body = nil)
13
- message = description
14
- message += " -- #{body}" if body
15
- super(message)
11
+ sig { params(body: String, details: T.nilable(String)).void }
12
+ def initialize(body, details: nil)
13
+ error_data = {
14
+ type: "parse",
15
+ body: body,
16
+ details: details
17
+ }
18
+
19
+ super(error_data.to_json)
16
20
  end
17
21
  end
18
22
  end
@@ -8,10 +8,16 @@ module Rager
8
8
  class TemplateError < Rager::Error
9
9
  extend T::Sig
10
10
 
11
- sig { params(input: Rager::Template::Input, message: String).void }
12
- def initialize(input, message)
13
- message = "Template Error: #{message} in #{input.template}"
14
- super(message)
11
+ sig { params(template: String, variables: T::Hash[Symbol, T.untyped], details: T.nilable(String)).void }
12
+ def initialize(template, variables, details: nil)
13
+ error_data = {
14
+ type: "template",
15
+ template: template,
16
+ variables: variables,
17
+ details: details
18
+ }
19
+
20
+ super(error_data.to_json)
15
21
  end
16
22
  end
17
23
  end
@@ -0,0 +1,25 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+
6
+ module Rager
7
+ module Errors
8
+ class TimeoutError < Rager::Error
9
+ extend T::Sig
10
+
11
+ sig { params(operation: String, timeout_seconds: T.nilable(Numeric), attempts: T.nilable(Integer), details: T.nilable(String)).void }
12
+ def initialize(operation, timeout_seconds: nil, attempts: nil, details: nil)
13
+ error_data = {
14
+ type: "timeout",
15
+ operation: operation,
16
+ timeout_seconds: timeout_seconds,
17
+ attempts: attempts,
18
+ details: details
19
+ }
20
+
21
+ super(error_data.to_json)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -11,7 +11,11 @@ module Rager
11
11
 
12
12
  sig { void }
13
13
  def initialize
14
- require "async/http"
14
+ begin
15
+ require "async/http"
16
+ rescue LoadError
17
+ raise Rager::Errors::DependencyError.new("async-http", details: "Please install the async-http gem to use the AsyncHttp adapter")
18
+ end
15
19
 
16
20
  @internet = T.let(Async::HTTP::Internet.new, Async::HTTP::Internet)
17
21
  end
@@ -22,22 +26,21 @@ module Rager
22
26
  ).returns(Rager::Http::Response)
23
27
  }
24
28
  def make_request(request)
25
- response = @internet.call(
26
- request.verb.serialize,
27
- request.url,
28
- request.headers.to_a,
29
- request.body
30
- )
29
+ response = wrap_if_timeout(request.timeout) do
30
+ @internet.call(
31
+ request.verb.serialize,
32
+ request.url,
33
+ request.headers.to_a,
34
+ request.body
35
+ )
36
+ end
31
37
 
32
38
  body = if response.body.nil?
33
39
  nil
34
- elsif (response.headers["Transfer-Encoding"]&.downcase == "chunked") ||
35
- response.headers["content-type"]&.downcase&.include?("text/event-stream")
40
+ elsif request.streaming
36
41
  body_enum(response)
37
42
  else
38
- body_parts = []
39
- response.body.each { |chunk| body_parts << chunk }
40
- body_parts.join.force_encoding("UTF-8")
43
+ response.body.join
41
44
  end
42
45
 
43
46
  Response.new(
@@ -45,9 +48,58 @@ module Rager
45
48
  headers: response.headers.to_h,
46
49
  body: body
47
50
  )
51
+ rescue SocketError => e
52
+ raise Rager::Errors::HttpError.new(
53
+ self,
54
+ request.url,
55
+ 0,
56
+ body: nil,
57
+ details: "DNS resolution failed: #{e.message}"
58
+ )
59
+ rescue Errno::ECONNREFUSED => e
60
+ raise Rager::Errors::HttpError.new(
61
+ self,
62
+ request.url,
63
+ 0,
64
+ body: nil,
65
+ details: "Connection refused: #{e.message}"
66
+ )
67
+ rescue Errno::ETIMEDOUT => e
68
+ raise Rager::Errors::HttpError.new(
69
+ self,
70
+ request.url,
71
+ 0,
72
+ body: nil,
73
+ details: "Connection timed out: #{e.message}"
74
+ )
75
+ rescue Async::TimeoutError => e
76
+ raise Rager::Errors::HttpError.new(
77
+ self,
78
+ request.url,
79
+ 0,
80
+ body: nil,
81
+ details: "Request timed out: #{e.message}"
82
+ )
83
+ rescue EOFError => e
84
+ raise Rager::Errors::HttpError.new(
85
+ self,
86
+ request.url,
87
+ 0,
88
+ body: nil,
89
+ details: "Connection closed unexpectedly: #{e.message}"
90
+ )
48
91
  end
49
92
 
50
- private
93
+ sig { params(timeout: T.nilable(Numeric), block: T.proc.returns(T.untyped)).returns(T.untyped) }
94
+ def wrap_if_timeout(timeout, &block)
95
+ if timeout
96
+ Async::Task.current.with_timeout(timeout) do
97
+ block.call
98
+ end
99
+ else
100
+ block.call
101
+ end
102
+ end
51
103
 
52
104
  sig {
53
105
  params(
@@ -56,7 +108,7 @@ module Rager
56
108
  }
57
109
  def body_enum(response)
58
110
  Enumerator.new do |yielder|
59
- response.body.each { |chunk| yielder << chunk.force_encoding("UTF-8") }
111
+ response.body.each { |chunk| yielder << chunk }
60
112
  ensure
61
113
  response.close
62
114
  end
@@ -1,8 +1,10 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "base64"
4
5
  require "fileutils"
5
6
  require "json"
7
+
6
8
  require "sorbet-runtime"
7
9
 
8
10
  module Rager
@@ -20,13 +22,9 @@ module Rager
20
22
  chunk_delimiter: T.nilable(String)
21
23
  ).void
22
24
  end
23
- def initialize(
24
- test_file_path,
25
- fallback_adapter = nil,
26
- chunk_delimiter = nil
27
- )
25
+ def initialize(test_file_path, fallback_adapter = nil, chunk_delimiter = nil)
28
26
  @test_file_path = T.let(test_file_path, String)
29
- @fallback_adapter = T.let(fallback_adapter || Rager::Http::Adapters::AsyncHttp.new, Rager::Http::Adapters::Abstract)
27
+ @fallback_adapter = T.let(fallback_adapter || Rager::Http::Adapters::NetHttp.new, Rager::Http::Adapters::Abstract)
30
28
  @cache = T.let(load_cache, Cache)
31
29
  end
32
30
 
@@ -34,48 +32,48 @@ module Rager
34
32
  def make_request(request)
35
33
  key = request.serialize.to_json
36
34
  cached_entry = @cache[key]
37
- if cached_entry
38
- build_response_from_cache(cached_entry)
39
- else
40
- fetch_and_cache_response(request, key)
41
- end
35
+ cached_entry ? build_response_from_cache(cached_entry) : fetch_and_cache_response(request, key)
42
36
  end
43
37
 
44
- sig {
45
- params(
46
- request: Rager::Http::Request,
47
- key: String
48
- ).returns(Rager::Http::Response)
49
- }
38
+ sig { params(request: Rager::Http::Request, key: String).returns(Rager::Http::Response) }
50
39
  def fetch_and_cache_response(request, key)
51
40
  response = @fallback_adapter.make_request(request)
52
41
 
53
- serialized_response = T.let({
42
+ serialized_response = {
54
43
  "status" => response.status,
55
44
  "headers" => response.headers
56
- }, T::Hash[String, T.untyped])
45
+ }
57
46
 
58
- if response.body.is_a?(Enumerator)
59
- chunks = T.let([], T::Array[String])
47
+ if request.streaming && response.body.is_a?(Enumerator)
48
+ raw_chunks = T.let([], T::Array[String])
49
+ T.cast(response.body, T::Enumerator[String]).each { |chunk| raw_chunks << chunk }
60
50
 
61
- T.cast(response.body, T::Enumerator[String]).each do |chunk|
62
- chunks << chunk
63
- end
51
+ has_binary = raw_chunks.any? { |chunk| binary_content?(chunk) }
52
+ chunks = raw_chunks.map { |chunk| binary_content?(chunk) ? Base64.strict_encode64(chunk) : chunk }
64
53
 
65
54
  serialized_response["body"] = chunks
66
55
  serialized_response["is_stream"] = true
56
+ serialized_response["is_binary"] = has_binary
67
57
 
68
58
  response_body = Enumerator.new do |yielder|
69
- chunks.each { |chunk| yielder << chunk }
59
+ raw_chunks.each { |chunk| yielder << chunk }
70
60
  end
71
61
  else
72
- serialized_response["body"] = response.body
62
+ body = T.cast(response.body, T.nilable(String)) || ""
63
+
64
+ if binary_content?(body)
65
+ serialized_response["body"] = Base64.strict_encode64(body)
66
+ serialized_response["is_binary"] = true
67
+ else
68
+ serialized_response["body"] = body
69
+ serialized_response["is_binary"] = false
70
+ end
71
+
73
72
  serialized_response["is_stream"] = false
74
- response_body = response.body
73
+ response_body = body
75
74
  end
76
75
 
77
76
  @cache[key] = serialized_response
78
-
79
77
  save_cache
80
78
 
81
79
  Rager::Http::Response.new(
@@ -85,19 +83,19 @@ module Rager
85
83
  )
86
84
  end
87
85
 
88
- sig {
89
- params(
90
- entry: T::Hash[String, T.untyped]
91
- ).returns(Rager::Http::Response)
92
- }
86
+ sig { params(entry: T::Hash[String, T.untyped]).returns(Rager::Http::Response) }
93
87
  def build_response_from_cache(entry)
94
88
  body = entry["body"]
95
89
  is_stream = entry["is_stream"] || false
90
+ is_binary = entry["is_binary"] || false
96
91
 
97
92
  body = if is_stream
98
- T.cast(body, T::Array[String]).to_enum
93
+ chunks = T.cast(body, T::Array[String])
94
+ Enumerator.new do |yielder|
95
+ chunks.each { |chunk| yielder << (is_binary ? Base64.strict_decode64(chunk) : chunk) }
96
+ end
99
97
  else
100
- body
98
+ is_binary ? Base64.strict_decode64(T.cast(body, String)) : body
101
99
  end
102
100
 
103
101
  Rager::Http::Response.new(
@@ -116,21 +114,19 @@ module Rager
116
114
  sig { returns(Cache) }
117
115
  def load_cache
118
116
  create_file_if_not_exists
119
- JSON.parse(File.read(@test_file_path, encoding: "UTF-8"))
117
+ JSON.parse(File.read(@test_file_path))
120
118
  end
121
119
 
122
120
  sig { void }
123
121
  def save_cache
124
- current_file_content =
125
- if File.exist?(@test_file_path)
126
- JSON.parse(File.read(@test_file_path, encoding: "UTF-8"))
127
- else
128
- {}
129
- end
130
-
122
+ current_file_content = File.exist?(@test_file_path) ? JSON.parse(File.read(@test_file_path)) : {}
131
123
  output = current_file_content.merge(@cache)
132
- json_string = JSON.generate(output).force_encoding("UTF-8")
133
- File.write(@test_file_path, json_string, encoding: "UTF-8")
124
+ File.write(@test_file_path, JSON.generate(output))
125
+ end
126
+
127
+ sig { params(content: String).returns(T::Boolean) }
128
+ def binary_content?(content)
129
+ content.include?("\0")
134
130
  end
135
131
  end
136
132
  end
@@ -0,0 +1,144 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "net/http"
5
+ require "uri"
6
+ require "sorbet-runtime"
7
+
8
+ module Rager
9
+ module Http
10
+ module Adapters
11
+ class NetHttp < Rager::Http::Adapters::Abstract
12
+ extend T::Sig
13
+
14
+ sig { void }
15
+ def initialize
16
+ end
17
+
18
+ sig {
19
+ override.params(
20
+ request: Rager::Http::Request
21
+ ).returns(Rager::Http::Response)
22
+ }
23
+ def make_request(request)
24
+ uri = URI(request.url)
25
+
26
+ http = Net::HTTP.new(uri.host, uri.port)
27
+ http.use_ssl = uri.scheme == "https"
28
+
29
+ if request.timeout
30
+ http.open_timeout = request.timeout
31
+ http.read_timeout = request.timeout
32
+ end
33
+
34
+ http_request = build_http_request(request, uri)
35
+
36
+ http.request(http_request) do |response|
37
+ body = if request.streaming
38
+ body_enum(response)
39
+ else
40
+ response.body
41
+ end
42
+
43
+ return Rager::Http::Response.new(
44
+ status: response.code.to_i,
45
+ headers: response.to_hash,
46
+ body: body
47
+ )
48
+ end
49
+ rescue SocketError => e
50
+ raise Rager::Errors::HttpError.new(
51
+ self,
52
+ request.url,
53
+ 0,
54
+ body: nil,
55
+ details: "DNS resolution failed: #{e.message}"
56
+ )
57
+ rescue Errno::ECONNREFUSED => e
58
+ raise Rager::Errors::HttpError.new(
59
+ self,
60
+ request.url,
61
+ 0,
62
+ body: nil,
63
+ details: "Connection refused: #{e.message}"
64
+ )
65
+ rescue Errno::EBUSY => e
66
+ raise Rager::Errors::HttpError.new(
67
+ self,
68
+ request.url,
69
+ 0,
70
+ body: nil,
71
+ details: "Device or resource busy: #{e.message}"
72
+ )
73
+ rescue Net::OpenTimeout => e
74
+ raise Rager::Errors::HttpError.new(
75
+ self,
76
+ request.url,
77
+ 0,
78
+ body: nil,
79
+ details: "Connection timed out: #{e.message}"
80
+ )
81
+ rescue Net::ReadTimeout => e
82
+ raise Rager::Errors::HttpError.new(
83
+ self,
84
+ request.url,
85
+ 0,
86
+ body: nil,
87
+ details: "Read timed out: #{e.message}"
88
+ )
89
+ rescue EOFError => e
90
+ raise Rager::Errors::HttpError.new(
91
+ self,
92
+ request.url,
93
+ 0,
94
+ body: nil,
95
+ details: "Connection closed unexpectedly: #{e.message}"
96
+ )
97
+ end
98
+
99
+ sig {
100
+ params(
101
+ response: Net::HTTPResponse
102
+ ).returns(T::Enumerator[String])
103
+ }
104
+ def body_enum(response)
105
+ chunks = T.let([], T::Array[String])
106
+
107
+ response.read_body do |chunk|
108
+ chunks << chunk
109
+ end
110
+
111
+ chunks.to_enum
112
+ end
113
+
114
+ sig {
115
+ params(
116
+ request: Rager::Http::Request,
117
+ uri: URI::Generic
118
+ ).returns(Net::HTTPRequest)
119
+ }
120
+ def build_http_request(request, uri)
121
+ http_request = case request.verb
122
+ when Rager::Http::Verb::Get then Net::HTTP::Get.new(uri)
123
+ when Rager::Http::Verb::Post then Net::HTTP::Post.new(uri)
124
+ when Rager::Http::Verb::Put then Net::HTTP::Put.new(uri)
125
+ when Rager::Http::Verb::Patch then Net::HTTP::Patch.new(uri)
126
+ when Rager::Http::Verb::Delete then Net::HTTP::Delete.new(uri)
127
+ when Rager::Http::Verb::Head then Net::HTTP::Head.new(uri)
128
+ when Rager::Http::Verb::Options then Net::HTTP::Options.new(uri)
129
+ end
130
+
131
+ request.headers.each do |key, value|
132
+ http_request[key] = value
133
+ end
134
+
135
+ if request.body && http_request.request_body_permitted?
136
+ http_request.body = request.body
137
+ end
138
+
139
+ http_request
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -10,6 +10,8 @@ module Rager
10
10
  const :verb, Rager::Http::Verb, default: Rager::Http::Verb::Get
11
11
  const :headers, T::Hash[String, String]
12
12
  const :body, T.nilable(String)
13
+ const :streaming, T::Boolean, default: false
14
+ const :timeout, T.nilable(Numeric)
13
15
  end
14
16
  end
15
17
  end
@@ -4,16 +4,17 @@
4
4
  require "sorbet-runtime"
5
5
 
6
6
  module Rager
7
- module ImageGen
7
+ module Image
8
8
  class Options < T::Struct
9
9
  extend T::Sig
10
10
  include Rager::Options
11
11
 
12
- const :provider, String, default: "replicate"
12
+ const :provider, Symbol, default: :replicate
13
13
  const :model, String, default: "black-forest-labs/flux-schnell"
14
- const :output_format, T.nilable(Rager::ImageGen::OutputFormat)
15
- const :api_key, T.nilable(String)
14
+ const :output_format, T.nilable(Rager::Image::OutputFormat)
16
15
  const :seed, T.nilable(Integer)
16
+ const :api_key, T.nilable(String)
17
+ const :timeout, T.nilable(Numeric)
17
18
  end
18
19
  end
19
20
  end
@@ -4,7 +4,7 @@
4
4
  require "sorbet-runtime"
5
5
 
6
6
  module Rager
7
- module ImageGen
7
+ module Image
8
8
  class OutputFormat < T::Enum
9
9
  extend T::Sig
10
10
 
@@ -4,7 +4,7 @@
4
4
  require "sorbet-runtime"
5
5
 
6
6
  module Rager
7
- module ImageGen
7
+ module Image
8
8
  module Providers
9
9
  class Abstract
10
10
  extend T::Sig
@@ -14,10 +14,10 @@ module Rager
14
14
  sig do
15
15
  abstract.params(
16
16
  prompt: String,
17
- options: Rager::ImageGen::Options
18
- ).returns(Rager::Types::ImageGenOutput)
17
+ options: Rager::Image::Options
18
+ ).returns(Rager::Types::ImageOutput)
19
19
  end
20
- def image_gen(prompt, options)
20
+ def image(prompt, options)
21
21
  end
22
22
  end
23
23
  end
@@ -5,15 +5,23 @@ require "sorbet-runtime"
5
5
  require "json"
6
6
 
7
7
  module Rager
8
- module ImageGen
8
+ module Image
9
9
  module Providers
10
- class Replicate < Rager::ImageGen::Providers::Abstract
10
+ class Replicate < Rager::Image::Providers::Abstract
11
11
  extend T::Sig
12
12
 
13
- sig { override.params(prompt: String, options: Rager::ImageGen::Options).returns(Rager::Types::ImageGenOutput) }
14
- def image_gen(prompt, options)
13
+ sig { override.params(prompt: String, options: Rager::Image::Options).returns(Rager::Types::ImageOutput) }
14
+ def image(prompt, options)
15
15
  api_key = options.api_key || ENV["REPLICATE_API_KEY"]
16
- raise Rager::Errors::MissingCredentialsError.new("Replicate", "REPLICATE_API_KEY") if api_key.nil?
16
+ raise Rager::Errors::CredentialsError.new("Replicate", env_var: ["REPLICATE_API_KEY"]) if api_key.nil?
17
+
18
+ url = "https://api.replicate.com/v1/models/#{options.model}/predictions"
19
+
20
+ headers = {
21
+ "Authorization" => "Bearer #{api_key}",
22
+ "Content-Type" => "application/json",
23
+ "Prefer" => "wait"
24
+ }
17
25
 
18
26
  body = {
19
27
  input: {
@@ -25,25 +33,22 @@ module Rager
25
33
  end
26
34
 
27
35
  request = Rager::Http::Request.new(
28
- url: "https://api.replicate.com/v1/models/#{options.model}/predictions",
36
+ url: url,
29
37
  verb: Rager::Http::Verb::Post,
30
- headers: {
31
- "Authorization" => "Bearer #{api_key}",
32
- "Content-Type" => "application/json",
33
- "Prefer" => "wait"
34
- },
35
- body: body.to_json
38
+ headers: headers,
39
+ body: body.to_json,
40
+ timeout: options.timeout || Rager.config.timeout
36
41
  )
37
42
 
38
43
  response = Rager.config.http_adapter.make_request(request)
39
44
  response_body = T.cast(T.must(response.body), String)
40
45
 
41
- raise Rager::Errors::HttpError.new(Rager.config.http_adapter, response.status, response_body) unless [200, 201].include?(response.status)
46
+ raise Rager::Errors::HttpError.new(Rager.config.http_adapter, request.url, response.status, body: response_body) unless [200, 201].include?(response.status)
42
47
 
43
48
  parsed = JSON.parse(response_body)
44
49
  parsed.fetch("output").first
45
50
  rescue JSON::ParserError, KeyError => e
46
- raise Rager::Errors::ParseError.new(e.message, response_body)
51
+ raise Rager::Errors::ParseError.new(response_body || "", details: e.message)
47
52
  end
48
53
  end
49
54
  end
@@ -4,8 +4,9 @@
4
4
  require "sorbet-runtime"
5
5
 
6
6
  module Rager
7
- class Logger < T::Enum
7
+ class LogStrategy < T::Enum
8
8
  enums do
9
+ None = new("none")
9
10
  Stdout = new("stdout")
10
11
  Remote = new("remote")
11
12
  end
@@ -4,16 +4,17 @@
4
4
  require "sorbet-runtime"
5
5
 
6
6
  module Rager
7
- module MeshGen
7
+ module Mesh
8
8
  class Options < T::Struct
9
9
  extend T::Sig
10
10
  include Rager::Options
11
11
 
12
- const :provider, String, default: "replicate"
12
+ const :provider, Symbol, default: :replicate
13
13
  const :model, String, default: "firoz/trellis"
14
14
  const :version, String, default: "4876f2a8da1c544772dffa32e8889da4a1bab3a1f5c1937bfcfccb99ae347251"
15
- const :api_key, T.nilable(String)
16
15
  const :seed, T.nilable(Integer)
16
+ const :api_key, T.nilable(String)
17
+ const :timeout, T.nilable(Numeric)
17
18
  end
18
19
  end
19
20
  end