gemini_cache 0.0.9 → 0.0.11

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: ae4847ce3abf808c2779601462af28a47989301593355a8a39977a5df495f322
4
- data.tar.gz: 71e72d0e2750d6b530d407f97a7490c65b6acbf342ad10803916b4b24d418b71
3
+ metadata.gz: 5f3682e46bf67ce3fae20c5e27210eafdadc25338a54eecfec4c9f48a726ce7a
4
+ data.tar.gz: '0393aa11b0f296e72cbd7604be9061ad0186df90cfaeb6d5665b4d77d893d700'
5
5
  SHA512:
6
- metadata.gz: 8ab29a93e9555626f6d1eecb189351b5d62b28805e0e90e0ba9c29cb9e5bcf8698f72dadb0621ffbf196503d186a2c341b45c387bc25f940d055bb110455ff78
7
- data.tar.gz: 50a917b60662ecd5bc1cef90c0a633febfcfbe294c297525d397f60863dfaa29977e43c0743c9f717452fa7d45ce5fe2da8f11f3816d0f65fa5e06f6632675ff
6
+ metadata.gz: 5caf764b56efeb6234a03248b9dca22d7f84d2a885e7dca10651b80c49c2c390f473db4cd92037965af2f2ee3718cc78565db2bb257963b8137a9504056590ea
7
+ data.tar.gz: fba129ed606d3c62a5f39149cd2359fd5d6c18d01a978ffee0bff4a3968fc2c9f2f49723ffe6421192399b021e0023d9766fc7601ebf321e9619ea2b54a77834
data/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # GeminiCache
2
+
3
+ GeminiCache é uma biblioteca Ruby para interagir com a API de Cache do Google Gemini. Ela fornece uma interface simples para criar, gerenciar e manipular caches de conteúdo para uso com os modelos de IA do Gemini.
4
+
5
+ ## Instalação
6
+
7
+ Adicione esta linha ao Gemfile da sua aplicação:
8
+
9
+ ```ruby
10
+ gem 'gemini_cache'
11
+ ```
12
+
13
+ E então execute:
14
+
15
+ ```bash
16
+ $ bundle install
17
+ ```
18
+
19
+ Ou instale manualmente:
20
+
21
+ ```bash
22
+ $ gem install gemini_cache
23
+ ```
24
+
25
+ ## Configuração
26
+
27
+ Antes de usar a biblioteca, você precisa configurar sua chave de API do Google Gemini. Você pode fazer isso de duas maneiras:
28
+
29
+ ### 1. Usando variáveis de ambiente
30
+
31
+ ```bash
32
+ export GEMINI_API_KEY='sua_chave_api_aqui'
33
+ ```
34
+
35
+ ### 2. Usando o bloco de configuração
36
+
37
+ ```ruby
38
+ GeminiCache.configure do |config|
39
+ config.api_key = 'sua_chave_api_aqui'
40
+ config.timeout = 30 # opcional, tempo limite em segundos
41
+ config.cache_dir = '/path/to/cache' # opcional, diretório para cache local
42
+ end
43
+ ```
44
+
45
+ ## Uso Básico
46
+
47
+ ### Inicializando o Cliente
48
+
49
+ ```ruby
50
+ cache = GeminiCache::Client.new
51
+ ```
52
+
53
+ ### Operações Básicas
54
+
55
+ #### Armazenando dados no cache
56
+
57
+ ```ruby
58
+ # Armazena um valor com uma chave
59
+ cache.set('minha_chave', 'meu_valor')
60
+
61
+ # Armazena com tempo de expiração (em segundos)
62
+ cache.set('minha_chave', 'meu_valor', expires_in: 3600)
63
+ ```
64
+
65
+ #### Recuperando dados do cache
66
+
67
+ ```ruby
68
+ # Recupera um valor
69
+ valor = cache.get('minha_chave')
70
+
71
+ # Recupera com valor padrão se a chave não existir
72
+ valor = cache.get('minha_chave', default: 'valor_padrao')
73
+ ```
74
+
75
+ #### Removendo dados do cache
76
+
77
+ ```ruby
78
+ # Remove uma chave específica
79
+ cache.delete('minha_chave')
80
+
81
+ # Limpa todo o cache
82
+ cache.clear
83
+ ```
84
+
85
+ ### Uso Avançado
86
+
87
+ #### Cache em Lote
88
+
89
+ ```ruby
90
+ # Armazena múltiplos valores
91
+ cache.set_multi({
92
+ 'chave1' => 'valor1',
93
+ 'chave2' => 'valor2'
94
+ })
95
+
96
+ # Recupera múltiplos valores
97
+ valores = cache.get_multi(['chave1', 'chave2'])
98
+ ```
99
+
100
+ #### Cache com Blocos
101
+
102
+ ```ruby
103
+ # Executa o bloco apenas se o valor não estiver em cache
104
+ resultado = cache.fetch('minha_chave') do
105
+ # código computacionalmente intensivo aqui
106
+ resultado_computado
107
+ end
108
+ ```
109
+
110
+ ## Exemplos de Uso com Gemini AI
111
+
112
+ ```ruby
113
+ # Cacheia resultados de chamadas à API do Gemini
114
+ resposta = cache.fetch('consulta_gemini') do
115
+ gemini_client.generate_content('Qual é o sentido da vida?')
116
+ end
117
+
118
+ # Cache com namespace para diferentes modelos
119
+ cache_pro = GeminiCache::Client.new(namespace: 'gemini-pro')
120
+ cache_vision = GeminiCache::Client.new(namespace: 'gemini-vision')
121
+ ```
122
+
123
+ ## Tratamento de Erros
124
+
125
+ ```ruby
126
+ begin
127
+ cache.get('minha_chave')
128
+ rescue GeminiCache::ConnectionError => e
129
+ puts "Erro de conexão: #{e.message}"
130
+ rescue GeminiCache::TimeoutError => e
131
+ puts "Tempo limite excedido: #{e.message}"
132
+ end
133
+ ```
134
+
135
+ ## Contribuindo
136
+
137
+ 1. Faça um fork do projeto
138
+ 2. Crie sua feature branch (`git checkout -b feature/nova-feature`)
139
+ 3. Faça commit das suas alterações (`git commit -am 'Adiciona nova feature'`)
140
+ 4. Faça push para a branch (`git push origin feature/nova-feature`)
141
+ 5. Crie um novo Pull Request
142
+
143
+ ## Licença
144
+
145
+ Esta gem está disponível como código aberto sob os termos da [Licença MIT](https://opensource.org/licenses/MIT).
@@ -0,0 +1,86 @@
1
+ module GeminiCache
2
+ # Client for making HTTP requests to the Gemini API
3
+ class ApiClient
4
+ # Error class for API-related errors
5
+ class ApiError < StandardError; end
6
+
7
+ # Initializes a new API client
8
+ def initialize
9
+ @conn = Faraday.new(
10
+ url: GeminiCache.configuration.api_base_url,
11
+ headers: { 'Content-Type' => 'application/json' }
12
+ )
13
+ end
14
+
15
+ # Creates a new cache
16
+ # @param content [String] JSON string of cache content
17
+ # @return [Hash] API response
18
+ # @raise [ApiError] if the request fails
19
+ def create_cache(content)
20
+ response = @conn.post('/v1beta/cachedContents') do |req|
21
+ req.params['key'] = api_key
22
+ req.body = content
23
+ end
24
+
25
+ handle_response(response)
26
+ end
27
+
28
+ # Lists all caches
29
+ # @return [Hash] API response
30
+ # @raise [ApiError] if the request fails
31
+ def list_caches
32
+ response = @conn.get('/v1beta/cachedContents') do |req|
33
+ req.params['key'] = api_key
34
+ end
35
+
36
+ handle_response(response)
37
+ end
38
+
39
+ # Updates an existing cache
40
+ # @param name [String] cache name
41
+ # @param content [String] JSON string of new content
42
+ # @return [Hash] API response
43
+ # @raise [ApiError] if the request fails
44
+ def update_cache(name, content)
45
+ response = @conn.patch("/v1beta/#{name}") do |req|
46
+ req.params['key'] = api_key
47
+ req.body = content
48
+ end
49
+
50
+ handle_response(response)
51
+ end
52
+
53
+ # Deletes a cache
54
+ # @param name [String] cache name
55
+ # @return [Hash] API response
56
+ # @raise [ApiError] if the request fails
57
+ def delete_cache(name)
58
+ response = @conn.delete("/v1beta/#{name}") do |req|
59
+ req.params['key'] = api_key
60
+ end
61
+
62
+ handle_response(response)
63
+ end
64
+
65
+ private
66
+
67
+ # Gets the API key from configuration or environment
68
+ # @return [String] API key
69
+ def api_key
70
+ GeminiCache.configuration.api_key || ENV.fetch('GEMINI_API_KEY')
71
+ end
72
+
73
+ # Handles API responses
74
+ # @param response [Faraday::Response] HTTP response
75
+ # @return [Hash] parsed response body
76
+ # @raise [ApiError] if response status is not 200
77
+ def handle_response(response)
78
+ return JSON.parse(response.body) if response.status == 200
79
+
80
+ error_message = JSON.parse(response.body)['error'] rescue response.body
81
+ raise ApiError, "API request failed (#{response.status}): #{error_message}"
82
+ rescue Faraday::Error => e
83
+ raise ApiError, "Network error: #{e.message}"
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,35 @@
1
+ module GeminiCache
2
+ # Configuration class for GeminiCache settings
3
+ # @attr [String] api_key The API key for Gemini API
4
+ # @attr [String] api_base_url The base URL for the Gemini API
5
+ # @attr [String] default_model The default model to use
6
+ # @attr [Integer] default_ttl The default time-to-live in seconds
7
+ class Configuration
8
+ attr_accessor :api_key, :api_base_url, :default_model, :default_ttl
9
+
10
+ # Initializes a new Configuration with default values
11
+ def initialize
12
+ @api_base_url = 'https://generativelanguage.googleapis.com'
13
+ @default_model = 'gemini-1.5-flash-8b'
14
+ @default_ttl = 300
15
+ end
16
+ end
17
+
18
+ class << self
19
+ # @return [Configuration] current configuration
20
+ def configuration
21
+ @configuration ||= Configuration.new
22
+ end
23
+
24
+ # Configures GeminiCache
25
+ # @yield [Configuration] configuration object
26
+ # @example
27
+ # GeminiCache.configure do |config|
28
+ # config.api_key = 'your-api-key'
29
+ # config.default_ttl = 600
30
+ # end
31
+ def configure
32
+ yield(configuration)
33
+ end
34
+ end
35
+ end
@@ -1,46 +1,89 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ItemExtender
2
- def delete = GeminiCache.delete(name: self['name'])
4
+ GEMINI_API_BASE_URL = 'https://generativelanguage.googleapis.com'
5
+ DEFAULT_TIMEOUT = 300 # seconds
6
+ ACCURATE_MODE_CONFIG = { temperature: 0, topP: 0, topK: 1 }.freeze
3
7
 
4
- def ttl=(new_ttl)
5
- GeminiCache.update(name: self['name'], content: { ttl: "#{new_ttl}s" })
6
- GeminiCache.get_by_name(name: self['name'])
8
+ # Deletes the cached item
9
+ # @return [void]
10
+ def delete
11
+ GeminiCache.delete(name: self['name'])
7
12
  end
8
13
 
14
+ # Updates the TTL of the cached item
15
+ # @param new_ttl [Integer] new TTL value in seconds
16
+ # @return [void]
17
+ def ttl=(new_ttl)
18
+ GeminiCache.update(name: self['name'], content: { ttl: "#{new_ttl}s" }.to_json)
19
+ end
20
+
21
+ # Generates content using the Gemini API
22
+ # @param contents [Array<Hash>] array of content parts
23
+ # @param generation_config [Hash, nil] optional generation configuration
24
+ # @return [Hash] response with added #content method
25
+ # @raise [GeminiAPIError] when the API request fails
9
26
  def generate_content(contents:, generation_config: nil)
10
- conn = Faraday.new(
11
- url: 'https://generativelanguage.googleapis.com',
27
+ response = api_client.post(generate_content_endpoint) do |req|
28
+ req.params['key'] = ENV.fetch('GEMINI_API_KEY')
29
+ req.body = build_request_body(contents, generation_config)
30
+ end
31
+
32
+ handle_response(response)
33
+ rescue Faraday::Error => e
34
+ raise GeminiAPIError, "Request failed: #{e.message}"
35
+ end
36
+
37
+ # Generates content from a single prompt
38
+ # @param prompt [String] the input prompt
39
+ # @param generation_config [Hash, Symbol] generation configuration or :accurate_mode
40
+ # @return [String] generated content
41
+ def single_prompt(prompt:, generation_config: :accurate_mode)
42
+ config = generation_config.eql?(:accurate_mode) ? ACCURATE_MODE_CONFIG : generation_config
43
+
44
+ generate_content(
45
+ contents: [{ parts: [{ text: prompt }], role: 'user' }],
46
+ generation_config: config
47
+ ).content
48
+ end
49
+
50
+ private
51
+
52
+ def api_client
53
+ @api_client ||= Faraday.new(
54
+ url: GEMINI_API_BASE_URL,
12
55
  headers: { 'Content-Type' => 'application/json' }
13
56
  ) do |f|
14
- f.options.timeout = 300 # timeout em segundos para a requisição completa
15
- f.options.open_timeout = 300 # timeout em segundos para abrir a conexão
57
+ f.options.timeout = DEFAULT_TIMEOUT
58
+ f.options.open_timeout = DEFAULT_TIMEOUT
16
59
  end
60
+ end
61
+
62
+ def generate_content_endpoint
63
+ "/v1beta/models/#{self['model'].split('/').last}:generateContent"
64
+ end
17
65
 
18
- body = {
66
+ def build_request_body(contents, generation_config)
67
+ {
19
68
  cached_content: self['name'],
20
- contents:
21
- }
69
+ contents: contents,
70
+ generation_config: generation_config
71
+ }.compact.to_json
72
+ end
22
73
 
23
- body[:generation_config] = generation_config if !generation_config.nil?
74
+ def handle_response(response)
75
+ return parse_successful_response(response) if response.status == 200
24
76
 
25
- response = conn.post("/v1beta/models/#{self['model'].split('/').last}:generateContent") do |req|
26
- req.params['key'] = ENV.fetch('GEMINI_API_KEY')
27
- req.body = body.to_json
28
- end
29
-
30
- if response.status == 200
31
- resp = JSON.parse(response.body)
32
- def resp.content = dig('candidates', 0, 'content', 'parts', 0, 'text')
33
- return resp
34
- end
77
+ raise GeminiAPIError, "Content generation failed: #{response.body}"
78
+ end
35
79
 
36
- raise "Erro ao gerar conteúdo: #{response.body}"
37
- rescue Faraday::Error => e
38
- raise "Erro na requisição: #{e.message}"
80
+ def parse_successful_response(response)
81
+ resp = JSON.parse(response.body)
82
+ def resp.content
83
+ dig('candidates', 0, 'content', 'parts', 0, 'text')
84
+ end
85
+ resp
39
86
  end
40
-
41
- def single_prompt(prompt:, generation_config: :accurate_mode)
42
- # accurate_mode: less creative, more accurate
43
- generation_config = { temperature: 0, topP: 0, topK: 1 } if generation_config.eql?(:accurate_mode)
44
- generate_content(contents: [{ parts: [{ text: prompt }], role: 'user' }], generation_config:).content
45
- end
46
87
  end
88
+
89
+ class GeminiAPIError < StandardError; end
data/lib/gemini_cache.rb CHANGED
@@ -4,122 +4,169 @@ require 'nokogiri'
4
4
  require 'json'
5
5
  require 'base64'
6
6
 
7
+ require 'gemini_cache/configuration'
8
+ require 'gemini_cache/api_client'
7
9
  require 'gemini_cache/item_extender'
8
10
 
11
+ # Module for interacting with Google's Gemini API cached contents
12
+ # @example Basic usage
13
+ # GeminiCache.configure do |config|
14
+ # config.api_key = 'your-api-key'
15
+ # end
16
+ #
17
+ # # Create a cache from text
18
+ # cache = GeminiCache.create_from_text(
19
+ # text: "Hello, world!",
20
+ # display_name: "my-cache"
21
+ # )
9
22
  module GeminiCache
10
- def self.read_local_file(path:, mime_type:) = { inline_data: { mime_type:, data: Base64.strict_encode64(File.read(path)) } }
11
- def self.read_remote_file(url:, mime_type:) = { inline_data: { mime_type:, data: Base64.strict_encode64(URI.open(url).read) } }
12
- def self.read_html(url:, default_remover: true)
13
- doc = Nokogiri::HTML(URI.open(url))
14
- %w[script style].each { |element| doc.css(element).each(&:remove) } if default_remover
23
+ # Custom error class for GeminiCache-specific errors
24
+ class Error < StandardError; end
15
25
 
16
- doc
17
- end
18
-
19
- def self.create(parts:, display_name:, model: 'gemini-1.5-flash-8b', ttl: 300)
20
- raise "Cache name already exist: '#{display_name}'" if GeminiCache.get_by_display_name(display_name:)
21
-
22
- content = {
23
- model: "models/#{model}",
24
- display_name:,
25
- contents: [parts:, role: 'user'],
26
- ttl: "#{ttl}s"
27
- }.to_json
28
-
29
- conn = Faraday.new(
30
- url: 'https://generativelanguage.googleapis.com',
31
- headers: { 'Content-Type' => 'application/json' }
32
- )
33
-
34
- response = conn.post('/v1beta/cachedContents') do |req|
35
- req.params['key'] = ENV.fetch('GEMINI_API_KEY')
36
- req.body = content
26
+ class << self
27
+ # Reads a local file and prepares it for the Gemini API
28
+ # @param path [String] path to the local file
29
+ # @param mime_type [String] MIME type of the file
30
+ # @return [Hash] formatted data for the API
31
+ def read_local_file(path:, mime_type:)
32
+ { inline_data: { mime_type:, data: Base64.strict_encode64(File.read(path)) } }
37
33
  end
38
-
39
- return get_by_name(name: JSON.parse(response.body)['name']) if response.status == 200
40
-
41
- raise "Erro ao criar cache: #{response.status} - #{response.body}"
42
- rescue Faraday::Error => e
43
- raise "Erro na requisição: #{e.message}"
44
- end
45
34
 
46
- def self.create_from_text(text:, display_name:, model: 'gemini-1.5-flash-8b', ttl: 300)
47
- GeminiCache.create(parts: [{ text: }], display_name:, model:, ttl:)
48
- end
35
+ # Reads a remote file and prepares it for the Gemini API
36
+ # @param url [String] URL of the remote file
37
+ # @param mime_type [String] MIME type of the file
38
+ # @return [Hash] formatted data for the API
39
+ def read_remote_file(url:, mime_type:)
40
+ { inline_data: { mime_type:, data: Base64.strict_encode64(URI.open(url).read) } }
41
+ end
49
42
 
50
- def self.create_from_webpage(url:, display_name:, model: 'gemini-1.5-flash-8b', ttl: 300)
51
- create_from_text(text: GeminiCache.read_html(url:).inner_text, display_name:, model:, ttl:)
52
- end
43
+ # Reads and parses HTML content from a URL
44
+ # @param url [String] URL of the webpage
45
+ # @param default_remover [Boolean] whether to remove script and style tags
46
+ # @return [Nokogiri::HTML::Document] parsed HTML document
47
+ def read_html(url:, default_remover: true)
48
+ doc = Nokogiri::HTML(URI.open(url))
49
+ %w[script style].each { |element| doc.css(element).each(&:remove) } if default_remover
50
+ doc
51
+ end
53
52
 
54
- def self.create_from_local_file(path:, mime_type:, display_name:, model: 'gemini-1.5-flash-8b', ttl: 300)
55
- GeminiCache.create(parts: GeminiCache.read_local_file(path:, mime_type:), display_name:, model:, ttl:)
56
- end
53
+ # Creates a new cache in the Gemini API
54
+ # @param parts [Array<Hash>] content parts to cache
55
+ # @param display_name [String] unique display name for the cache
56
+ # @param on_conflict [:raise_error, :get_existing] action to take if cache exists
57
+ # @param model [String, nil] Gemini model to use
58
+ # @param ttl [Integer, nil] time-to-live in seconds
59
+ # @return [Hash] created cache data
60
+ # @raise [Error] if cache already exists and on_conflict is :raise_error
61
+ def create(parts:, display_name:, on_conflict: :raise_error, model: nil, ttl: nil)
62
+ existing_cache = find_by_display_name(display_name:)
63
+
64
+ if existing_cache
65
+ case on_conflict
66
+ when :raise_error
67
+ raise Error, "Cache with display name '#{display_name}' already exists"
68
+ when :get_existing
69
+ return existing_cache
70
+ end
71
+ end
72
+
73
+ content = {
74
+ model: "models/#{model || configuration.default_model}",
75
+ display_name: display_name,
76
+ contents: [{ parts:, role: 'user' }],
77
+ ttl: "#{ttl || configuration.default_ttl}s"
78
+ }
79
+
80
+ response = api_client.create_cache(content.to_json)
81
+ find_by_name(name: response['name'])
82
+ end
57
83
 
58
- def self.create_from_remote_file(url:, mime_type:, display_name:, model: 'gemini-1.5-flash-8b', ttl: 300)
59
- GeminiCache.create(parts: GeminiCache.read_remote_file(url:, mime_type:), display_name:, model:, ttl:)
60
- end
84
+ # Creates a cache from plain text
85
+ # @param text [String] text content to cache
86
+ # @param options [Hash] additional options passed to #create
87
+ # @return [Hash] created cache data
88
+ def create_from_text(text:, **options)
89
+ create(parts: [{ text: }], **options)
90
+ end
61
91
 
62
- def self.get_by_name(name: nil) = GeminiCache.list.find { |item| item['name'].eql? name }
63
- def self.get_by_display_name(display_name: nil) = GeminiCache.list.find { |item| item['displayName'].eql? display_name }
92
+ # Creates a cache from a webpage's content
93
+ # @param url [String] URL of the webpage
94
+ # @param options [Hash] additional options passed to #create
95
+ # @return [Hash] created cache data
96
+ def create_from_webpage(url:, **options)
97
+ create_from_text(text: read_html(url:).inner_text, **options)
98
+ end
64
99
 
65
- def self.list
66
- conn = Faraday.new(
67
- url: 'https://generativelanguage.googleapis.com',
68
- headers: { 'Content-Type' => 'application/json' }
69
- )
100
+ # Creates a cache from a local file
101
+ # @param path [String] path to the local file
102
+ # @param mime_type [String] MIME type of the file
103
+ # @param options [Hash] additional options passed to #create
104
+ # @return [Hash] created cache data
105
+ def create_from_local_file(path:, mime_type:, **options)
106
+ file_data = read_local_file(path: path, mime_type: mime_type)
107
+ create(parts: [file_data], **options)
108
+ end
70
109
 
71
- response = conn.get("/v1beta/cachedContents") do |req|
72
- req.params['key'] = ENV.fetch('GEMINI_API_KEY')
110
+ # Creates a cache from a remote file
111
+ # @param url [String] URL of the remote file
112
+ # @param mime_type [String] MIME type of the file
113
+ # @param options [Hash] additional options passed to #create
114
+ # @return [Hash] created cache data
115
+ def create_from_remote_file(url:, mime_type:, **options)
116
+ file_data = read_remote_file(url: url, mime_type: mime_type)
117
+ create(parts: [file_data], **options)
73
118
  end
74
-
75
- return [] if JSON.parse(response.body).empty?
76
119
 
77
- JSON.parse(response.body)['cachedContents'].map { |item| item.extend(ItemExtender) }
120
+ # Lists all available caches
121
+ # @return [Array<Hash>] list of caches with ItemExtender mixed in
122
+ def list
123
+ response = api_client.list_caches
124
+ return [] if response.empty?
78
125
 
79
- rescue Faraday::Error => e
80
- raise "Erro na requisição: #{e.message}"
81
- end
82
-
83
- def self.update(name:, content:)
84
- conn = Faraday.new(
85
- url: 'https://generativelanguage.googleapis.com',
86
- headers: { 'Content-Type' => 'application/json' }
87
- )
88
-
89
- response = conn.patch("/v1beta/#{name}") do |req|
90
- req.params['key'] = ENV.fetch('GEMINI_API_KEY')
91
- req.body = content.to_json
126
+ response['cachedContents'].map { |item| item.extend(ItemExtender) }
92
127
  end
93
128
 
94
- return JSON.parse(response.body) if response.status == 200
95
-
96
- raise "Erro ao atualizar cache: #{response.body}"
97
- rescue Faraday::Error => e
98
- raise "Erro na requisição: #{e.message}"
99
- end
100
-
101
- def self.delete(name:)
102
- conn = Faraday.new(
103
- url: 'https://generativelanguage.googleapis.com',
104
- headers: { 'Content-Type' => 'application/json' }
105
- )
129
+ # Finds a cache by its internal name
130
+ # @param name [String] internal name of the cache
131
+ # @return [Hash, nil] cache data if found, nil otherwise
132
+ def find_by_name(name:)
133
+ list.find { |item| item['name'].eql?(name) }
134
+ end
106
135
 
107
- response = conn.delete("/v1beta/#{name}") do |req|
108
- req.params['key'] = ENV.fetch('GEMINI_API_KEY')
136
+ # Finds a cache by its display name
137
+ # @param display_name [String] display name of the cache
138
+ # @return [Hash, nil] cache data if found, nil otherwise
139
+ def find_by_display_name(display_name:)
140
+ list.find { |item| item['displayName'].eql?(display_name) }
109
141
  end
110
142
 
111
- return true if response.status == 200
112
-
113
- raise "Erro ao deletar cache: #{response.body}"
114
- rescue Faraday::Error => e
115
- raise "Erro na requisição: #{e.message}"
116
- end
143
+ # Updates an existing cache
144
+ # @param name [String] internal name of the cache
145
+ # @param content [Hash] new content for the cache
146
+ # @return [Hash] updated cache data
147
+ def update(name:, content:)
148
+ api_client.update_cache(name, content)
149
+ end
117
150
 
118
- def self.delete_all
119
- GeminiCache.list.each { |item| item.delete }
120
- end
151
+ # Deletes a specific cache
152
+ # @param name [String] internal name of the cache to delete
153
+ # @return [Boolean] true if successful
154
+ def delete(name:)
155
+ api_client.delete_cache(name)
156
+ true
157
+ end
121
158
 
122
- class << self
159
+ # Deletes all caches
160
+ # @return [void]
161
+ def delete_all
162
+ list.each { |item| item.delete }
163
+ end
123
164
  alias clear delete_all
165
+
166
+ private
167
+
168
+ def api_client
169
+ @api_client ||= ApiClient.new
170
+ end
124
171
  end
125
172
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gemini_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gedean Dias
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-23 00:00:00.000000000 Z
11
+ date: 2024-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -58,7 +58,10 @@ executables: []
58
58
  extensions: []
59
59
  extra_rdoc_files: []
60
60
  files:
61
+ - README.md
61
62
  - lib/gemini_cache.rb
63
+ - lib/gemini_cache/api_client.rb
64
+ - lib/gemini_cache/configuration.rb
62
65
  - lib/gemini_cache/item_extender.rb
63
66
  homepage: https://github.com/gedean/gemini_cache
64
67
  licenses: