30 def self.get_download_url(prediction_url, key = nil, http_adapter: nil)
31 api_key = ENV["REPLICATE_API_KEY"]
32 raise Rager::Errors::CredentialsError.new("Replicate", env_var: ["REPLICATE_API_KEY"]) if api_key.nil?
33
34 adapter = http_adapter || Rager.config.http_adapter
35 response = adapter.make_request(
36 Rager::Http::Request.new(
37 url: prediction_url,
38 headers: {"Authorization" => "Bearer #{api_key}", "Content-Type" => "application/json"}
39 )
40 )
41
42 raise Rager::Errors::HttpError.new(adapter, prediction_url, response.status, body: response.body&.to_s) unless response.success?
43
44 data = JSON.parse(T.cast(T.must(response.body), String))
45 return nil if ["starting", "processing"].include?(data["status"])
46
47 if data["status"] == "failed"
48 error_msg = data["error"] || "Prediction failed"
49 raise Rager::Errors::HttpError.new(adapter, prediction_url, 422, body: error_msg)
50 end
51
52 return nil unless data["status"] == "succeeded"
53
54 output = data["output"]
55 return nil if output.nil?
56
57 download_url = if key && output.is_a?(Hash) && output[key]
58 output[key]
59 elsif output.is_a?(Hash)
60 output.values.compact.first
61 elsif output.is_a?(Array) && !output.empty?
62 output.first
63 else
64 output.to_s
65 end
66
67 return nil if download_url.nil? || download_url.empty?
68 download_url
69 rescue JSON::ParserError => e
70 raise Rager::Errors::ParseError.new("Failed to parse prediction response", details: e.message)
71 end