Class: Riffer::Providers::Gemini::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/riffer/providers/gemini/client.rb,
sig/generated/riffer/providers/gemini/client.rbs

Overview

HTTP transport for the Gemini REST API. Riffer builds one from the configured api_key by default; construct your own to tune the HTTP knobs and assign it to Riffer.config.gemini.client. Any object implementing post and post_stream with these contracts works there — the class is a default implementation, not a required base.

Riffer.configure do |config|
config.gemini.client = Riffer::Providers::Gemini::Client.new(
  api_key: ENV["GEMINI_API_KEY"],
  read_timeout: 120
)
end

Constant Summary collapse

DEFAULT_BASE_URL =

RBS:

  • @api_key: String?

  • @base_url: String

  • @open_timeout: Integer

  • @read_timeout: Integer

  • @write_timeout: Integer?

  • @proxy_address: String?

  • @proxy_port: Integer?

Returns:

  • (String)
"https://generativelanguage.googleapis.com"
DEFAULT_OPEN_TIMEOUT =

Signature:

  • String

Returns:

  • (Integer)
10
DEFAULT_READ_TIMEOUT =

Signature:

  • Integer

Returns:

  • (Integer)
60

Instance Method Summary collapse

Constructor Details

#initialize(api_key: nil, base_url: DEFAULT_BASE_URL, open_timeout: DEFAULT_OPEN_TIMEOUT, read_timeout: DEFAULT_READ_TIMEOUT, write_timeout: nil, proxy_address: nil, proxy_port: nil) ⇒ Client

: (?api_key: String?, ?base_url: String, ?open_timeout: Integer, ?read_timeout: Integer, ?write_timeout: Integer?, ?proxy_address: String?, ?proxy_port: Integer?) -> void

Parameters:

  • api_key: (String, nil) (defaults to: nil)
  • base_url: (String) (defaults to: DEFAULT_BASE_URL)
  • open_timeout: (Integer) (defaults to: DEFAULT_OPEN_TIMEOUT)
  • read_timeout: (Integer) (defaults to: DEFAULT_READ_TIMEOUT)
  • write_timeout: (Integer, nil) (defaults to: nil)
  • proxy_address: (String, nil) (defaults to: nil)
  • proxy_port: (Integer, nil) (defaults to: nil)


34
35
36
37
38
39
40
41
42
43
44
# File 'lib/riffer/providers/gemini/client.rb', line 34

def initialize(api_key: nil, base_url: DEFAULT_BASE_URL, open_timeout: DEFAULT_OPEN_TIMEOUT,
               read_timeout: DEFAULT_READ_TIMEOUT, write_timeout: nil,
               proxy_address: nil, proxy_port: nil)
  @api_key = api_key
  @base_url = base_url
  @open_timeout = open_timeout
  @read_timeout = read_timeout
  @write_timeout = write_timeout
  @proxy_address = proxy_address
  @proxy_port = proxy_port
end

Instance Method Details

#build_request(uri, body) ⇒ Net::HTTP::Post

-- : (URI::Generic, Hash[Symbol, untyped]) -> Net::HTTP::Post

Parameters:

  • (URI::Generic)
  • (Hash[Symbol, untyped])

Returns:

  • (Net::HTTP::Post)


83
84
85
86
87
88
89
# File 'lib/riffer/providers/gemini/client.rb', line 83

def build_request(uri, body)
  request = Net::HTTP::Post.new(uri)
  request["Content-Type"] = "application/json"
  request["x-goog-api-key"] = @api_key
  request.body = body.to_json
  request
end

#handle_api_error!(response) ⇒ void

This method returns an undefined value.

-- : (Net::HTTPResponse) -> void

Parameters:

  • (Net::HTTPResponse)


111
112
113
114
115
116
117
118
119
# File 'lib/riffer/providers/gemini/client.rb', line 111

def handle_api_error!(response)
  parsed = begin
    JSON.parse(response.body, symbolize_names: true)
  rescue JSON::ParserError
    { message: response.body }
  end
  error_message = parsed.dig(:error, :message) || parsed[:message] || response.body
  raise Riffer::Error, "Gemini API error (#{response.code}): #{error_message}"
end

#post(path, body) ⇒ Hash[Symbol, untyped]

POSTs a JSON body to an API path and returns the parsed response hash. Raises Riffer::Error when the API responds with a non-success status.

: (String, Hash[Symbol, untyped]) -> Hash[Symbol, untyped]

Parameters:

  • (String)
  • (Hash[Symbol, untyped])

Returns:

  • (Hash[Symbol, untyped])


50
51
52
53
54
55
# File 'lib/riffer/providers/gemini/client.rb', line 50

def post(path, body)
  uri = URI("#{@base_url}/#{path}")
  response = start_http(uri) { |http| http.request(build_request(uri, body)) }
  handle_api_error!(response) unless response.is_a?(Net::HTTPSuccess)
  JSON.parse(response.body, symbolize_names: true)
end

#post_stream(path, body) {|arg0| ... } ⇒ void

This method returns an undefined value.

POSTs a JSON body to an API path, yielding raw response body chunks as they arrive. Raises Riffer::Error when the API responds with a non-success status.

: (String, Hash[Symbol, untyped]) { (String) -> void } -> void

Parameters:

  • (String)
  • (Hash[Symbol, untyped])

Yields:

Yield Parameters:

  • arg0 (String)

Yield Returns:

  • (void)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/riffer/providers/gemini/client.rb', line 62

def post_stream(path, body, &block)
  uri = URI("#{@base_url}/#{path}")
  start_http(uri) do |http|
    http.request(build_request(uri, body)) do |response|
      handle_api_error!(response) unless response.is_a?(Net::HTTPSuccess)

      begin
        response.read_body(&block)
      rescue IOError
        # A pre-buffered body (VCR/WebMock playback) raises IOError on a
        # streaming read; hand over the full body instead.
        yield(response.body)
      end
    end
  end
end

#start_http(uri) ⇒ void

This method returns an undefined value.

-- : [R] (URI::Generic) { (Net::HTTP) -> R } -> R



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/riffer/providers/gemini/client.rb', line 93

def start_http(uri, &)
  host = uri.hostname #: String
  options = {
    use_ssl: uri.scheme == "https",
    open_timeout: @open_timeout,
    read_timeout: @read_timeout,
  } #: Hash[Symbol, untyped]
  options[:write_timeout] = @write_timeout if @write_timeout

  if @proxy_address
    Net::HTTP.start(host, uri.port, @proxy_address, @proxy_port, nil, nil, **options, &)
  else
    Net::HTTP.start(host, uri.port, **options, &)
  end
end