Class: LittleGhost::Providers::Gemini

Inherits:
Base
  • Object
show all
Defined in:
lib/little_ghost/providers/gemini.rb,
lib/little_ghost/providers/gemini/catalog_source.rb

Overview

Connects a Model to Google's Gemini generateContent API.

Requests send messages, Tool definitions, attachments, and model settings to the configured Google endpoint. The adapter reads its API key from trusted configuration, honors cancellation and deadlines, and emits LittleGhost StreamEvents. HTTP and response-shape failures become ProviderError subclasses. It uses the built-in HTTP client and does not require Google's SDK.

Direct Known Subclasses

VertexAI

Defined Under Namespace

Classes: CatalogSource, Normalizer

Constant Summary collapse

DEFAULT_BASE_URL =

:nodoc:

"https://generativelanguage.googleapis.com/v1beta/"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#embed, #prepare_request

Constructor Details

#initialize(api_key:, model:, base_url: DEFAULT_BASE_URL, open_timeout: 10, read_timeout: 120, max_response_bytes: Support::HTTPClient::DEFAULT_MAX_RESPONSE_BYTES, transport: nil) ⇒ Gemini

Creates a Gemini generateContent client for model.

Raises:



30
31
32
33
34
35
36
37
# File 'lib/little_ghost/providers/gemini.rb', line 30

def initialize(api_key:, model:, base_url: DEFAULT_BASE_URL, open_timeout: 10, read_timeout: 120,
  max_response_bytes: Support::HTTPClient::DEFAULT_MAX_RESPONSE_BYTES, transport: nil, **)
  raise CredentialError, "Gemini api_key is required" if api_key.to_s.empty?

  @api_key = api_key
  @model = model
  @transport = transport || Support::HTTPClient.new(base_url:, open_timeout:, read_timeout:, max_response_bytes:)
end

Instance Attribute Details

#modelObject (readonly)

Provider-owned model identifier.



27
28
29
# File 'lib/little_ghost/providers/gemini.rb', line 27

def model
  @model
end

Class Method Details

.request_optionsObject

Request policy supported by Gemini and Vertex AI HTTP clients.



22
# File 'lib/little_ghost/providers/gemini.rb', line 22

def self.request_options = %i[max_response_bytes open_timeout read_timeout].freeze

Instance Method Details

#capabilities(metadata: {}) ⇒ Object

Reports Tool and structured-output support from model metadata.



61
62
63
64
# File 'lib/little_ghost/providers/gemini.rb', line 61

def capabilities(metadata: {})
  ModelCapabilities.new(native_structured_output: true, tools: true, tool_choice: true,
    supported_parameters: [:supported_parameters])
end

#stream(request) ⇒ Object

Streams normalized events for request.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/little_ghost/providers/gemini.rb', line 40

def stream(request)
  return enum_for(__method__, request) unless block_given?

  parser = Support::SSEParser.new
  normalizer = Normalizer.new(model:)
  @transport.stream(
    path: endpoint,
    headers: request_headers(request),
    body: JSON.generate(request_body(request)),
    cancellation_token: request.cancellation_token,
    deadline: request.deadline
  ) do |chunk|
    parser.<<(chunk).each { |data| normalizer.consume(JSON.parse(data)).each { |event| yield event } }
  end
  parser.finish.each { |data| normalizer.consume(JSON.parse(data)).each { |event| yield event } }
  normalizer.finish.each { |event| yield event }
rescue JSON::ParserError => error
  raise ProtocolError, "Google returned invalid JSON: #{error.message}"
end