gemini_craft 0.1.0 → 0.1.2
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 +4 -4
 - data/lib/gemini_craft/cache.rb +57 -0
 - data/lib/gemini_craft/client.rb +173 -0
 - data/lib/gemini_craft/configuration.rb +29 -0
 - data/lib/gemini_craft/error.rb +12 -0
 - data/lib/gemini_craft/version.rb +1 -1
 - metadata +6 -8
 - data/.rspec +0 -3
 - data/.rubocop.yml +0 -8
 - data/Gemfile +0 -13
 - data/Rakefile +0 -12
 - data/bin/console +0 -11
 - data/bin/setup +0 -8
 - data/sig/gemini_craft.rbs +0 -4
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 272eb66f29c87c7681a0f703ac2d3d697ef6ce23a6f067565179b623adfa6d85
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 6ccdc9d479c0fa4f2d28b15d9e45c72115ae841f28d2163cff367875b565dfb3
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: c9344da16d0a82761e10bcff5717ea5ca0c4b9dc31386e7814668875abcc2d2e3d916a95c18ef80154feaf4a659d7667a8e97f0f99c4ab39f70fe78f8487fa27
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: bd822c34dc245184c0fc7c4843898d93fc20c4dae4a0771df7be3ef9885712ecd4c1874446646952984bc639de4e340856f3d5f60249634a354b3bf1f899ea5b
         
     | 
| 
         @@ -0,0 +1,57 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "digest"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module GeminiCraft
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Simple in-memory cache for API responses
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Cache
         
     | 
| 
      
 8 
     | 
    
         
            +
                # Initialize the cache
         
     | 
| 
      
 9 
     | 
    
         
            +
                # @param config [GeminiCraft::Configuration] Configuration object
         
     | 
| 
      
 10 
     | 
    
         
            +
                def initialize(config)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @config = config
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @store = {}
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @timestamps = {}
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                # Get a value from the cache
         
     | 
| 
      
 17 
     | 
    
         
            +
                # @param key [String] Cache key
         
     | 
| 
      
 18 
     | 
    
         
            +
                # @return [String, nil] Cached value or nil if not found/expired
         
     | 
| 
      
 19 
     | 
    
         
            +
                def get(key)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  return nil unless @store.key?(key)
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  # Check if the entry has expired
         
     | 
| 
      
 23 
     | 
    
         
            +
                  if Time.now.to_i - @timestamps[key] > @config.cache_ttl
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @store.delete(key)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @timestamps.delete(key)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    return nil
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  @store[key]
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                # Set a value in the cache
         
     | 
| 
      
 33 
     | 
    
         
            +
                # @param key [String] Cache key
         
     | 
| 
      
 34 
     | 
    
         
            +
                # @param value [String] Value to cache
         
     | 
| 
      
 35 
     | 
    
         
            +
                def set(key, value)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @store[key] = value
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @timestamps[key] = Time.now.to_i
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                # Clear the entire cache
         
     | 
| 
      
 41 
     | 
    
         
            +
                def clear
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @store.clear
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @timestamps.clear
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                # Remove expired entries from the cache
         
     | 
| 
      
 47 
     | 
    
         
            +
                def cleanup
         
     | 
| 
      
 48 
     | 
    
         
            +
                  current_time = Time.now.to_i
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @timestamps.each do |key, timestamp|
         
     | 
| 
      
 50 
     | 
    
         
            +
                    if current_time - timestamp > @config.cache_ttl
         
     | 
| 
      
 51 
     | 
    
         
            +
                      @store.delete(key)
         
     | 
| 
      
 52 
     | 
    
         
            +
                      @timestamps.delete(key)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,173 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "faraday"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "faraday/retry"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "json"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module GeminiCraft
         
     | 
| 
      
 8 
     | 
    
         
            +
              # Client for interacting with the Gemini API
         
     | 
| 
      
 9 
     | 
    
         
            +
              class Client
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :config, :cache
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                # Initialize a new client
         
     | 
| 
      
 13 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @config = GeminiCraft.configuration
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @config.validate!
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @cache = Cache.new(@config)
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                # Generate content using Gemini
         
     | 
| 
      
 20 
     | 
    
         
            +
                # @param text [String] The text prompt to send to Gemini
         
     | 
| 
      
 21 
     | 
    
         
            +
                # @param system_instruction [String, nil] Optional system instruction to guide the model
         
     | 
| 
      
 22 
     | 
    
         
            +
                # @param options [Hash] Additional options for the request
         
     | 
| 
      
 23 
     | 
    
         
            +
                # @return [String] The generated content
         
     | 
| 
      
 24 
     | 
    
         
            +
                def generate_content(text, system_instruction = nil, options = {})
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # Create cache key from the request parameters
         
     | 
| 
      
 26 
     | 
    
         
            +
                  cache_key = generate_cache_key(text, system_instruction, options)
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  # Check cache if enabled
         
     | 
| 
      
 29 
     | 
    
         
            +
                  if @config.cache_enabled && (cached_response = @cache.get(cache_key))
         
     | 
| 
      
 30 
     | 
    
         
            +
                    return cached_response
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  # Prepare request payload
         
     | 
| 
      
 34 
     | 
    
         
            +
                  payload = build_payload(text, system_instruction, options)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  # Send request to API
         
     | 
| 
      
 37 
     | 
    
         
            +
                  response = make_request("models/#{@config.model}:generateContent", payload)
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  # Process response
         
     | 
| 
      
 40 
     | 
    
         
            +
                  content = extract_content(response)
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  # Cache response if enabled
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @cache.set(cache_key, content) if @config.cache_enabled
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  content
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                private
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                # Build the API request payload
         
     | 
| 
      
 51 
     | 
    
         
            +
                # @param text [String] The text prompt
         
     | 
| 
      
 52 
     | 
    
         
            +
                # @param system_instruction [String, nil] Optional system instruction
         
     | 
| 
      
 53 
     | 
    
         
            +
                # @param options [Hash] Additional options
         
     | 
| 
      
 54 
     | 
    
         
            +
                # @return [Hash] The request payload
         
     | 
| 
      
 55 
     | 
    
         
            +
                def build_payload(text, system_instruction, options)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  payload = {
         
     | 
| 
      
 57 
     | 
    
         
            +
                    contents: [
         
     | 
| 
      
 58 
     | 
    
         
            +
                      {
         
     | 
| 
      
 59 
     | 
    
         
            +
                        parts: [
         
     | 
| 
      
 60 
     | 
    
         
            +
                          {
         
     | 
| 
      
 61 
     | 
    
         
            +
                            text: text
         
     | 
| 
      
 62 
     | 
    
         
            +
                          }
         
     | 
| 
      
 63 
     | 
    
         
            +
                        ]
         
     | 
| 
      
 64 
     | 
    
         
            +
                      }
         
     | 
| 
      
 65 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 66 
     | 
    
         
            +
                  }
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  # Add system instruction if provided
         
     | 
| 
      
 69 
     | 
    
         
            +
                  if system_instruction
         
     | 
| 
      
 70 
     | 
    
         
            +
                    payload[:system_instruction] = {
         
     | 
| 
      
 71 
     | 
    
         
            +
                      parts: [
         
     | 
| 
      
 72 
     | 
    
         
            +
                        {
         
     | 
| 
      
 73 
     | 
    
         
            +
                          text: system_instruction
         
     | 
| 
      
 74 
     | 
    
         
            +
                        }
         
     | 
| 
      
 75 
     | 
    
         
            +
                      ]
         
     | 
| 
      
 76 
     | 
    
         
            +
                    }
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  # Merge additional options if provided
         
     | 
| 
      
 80 
     | 
    
         
            +
                  payload.merge!(options) if options && !options.empty?
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  payload
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                # Make a request to the Gemini API
         
     | 
| 
      
 86 
     | 
    
         
            +
                # @param endpoint [String] API endpoint
         
     | 
| 
      
 87 
     | 
    
         
            +
                # @param payload [Hash] Request payload
         
     | 
| 
      
 88 
     | 
    
         
            +
                # @return [Hash] Parsed response
         
     | 
| 
      
 89 
     | 
    
         
            +
                # @raise [GeminiCraft::APIError] If the API returns an error
         
     | 
| 
      
 90 
     | 
    
         
            +
                def make_request(endpoint, payload)
         
     | 
| 
      
 91 
     | 
    
         
            +
                  response = connection.post(endpoint) do |req|
         
     | 
| 
      
 92 
     | 
    
         
            +
                    req.params["key"] = @config.api_key
         
     | 
| 
      
 93 
     | 
    
         
            +
                    req.headers["Content-Type"] = "application/json"
         
     | 
| 
      
 94 
     | 
    
         
            +
                    req.body = JSON.generate(payload)
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                  handle_response(response)
         
     | 
| 
      
 98 
     | 
    
         
            +
                rescue Faraday::Error => e
         
     | 
| 
      
 99 
     | 
    
         
            +
                  raise APIError, "API request failed: #{e.message}"
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                # Set up a Faraday connection with retry logic
         
     | 
| 
      
 103 
     | 
    
         
            +
                # @return [Faraday::Connection] Configured connection
         
     | 
| 
      
 104 
     | 
    
         
            +
                def connection
         
     | 
| 
      
 105 
     | 
    
         
            +
                  Faraday.new(url: @config.api_base_url) do |faraday|
         
     | 
| 
      
 106 
     | 
    
         
            +
                    faraday.options.timeout = @config.timeout
         
     | 
| 
      
 107 
     | 
    
         
            +
                    faraday.request :retry, max: @config.max_retries, interval: 0.5,
         
     | 
| 
      
 108 
     | 
    
         
            +
                                            interval_randomness: 0.5, backoff_factor: 2,
         
     | 
| 
      
 109 
     | 
    
         
            +
                                            exceptions: [Faraday::TimeoutError, Faraday::ConnectionFailed]
         
     | 
| 
      
 110 
     | 
    
         
            +
                    faraday.adapter Faraday.default_adapter
         
     | 
| 
      
 111 
     | 
    
         
            +
                  end
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                # Handle and parse the API response
         
     | 
| 
      
 115 
     | 
    
         
            +
                # @param response [Faraday::Response] The API response
         
     | 
| 
      
 116 
     | 
    
         
            +
                # @return [Hash] Parsed response body
         
     | 
| 
      
 117 
     | 
    
         
            +
                # @raise [GeminiCraft::APIError] If the API returns an error
         
     | 
| 
      
 118 
     | 
    
         
            +
                def handle_response(response)
         
     | 
| 
      
 119 
     | 
    
         
            +
                  case response.status
         
     | 
| 
      
 120 
     | 
    
         
            +
                  when 200
         
     | 
| 
      
 121 
     | 
    
         
            +
                    JSON.parse(response.body)
         
     | 
| 
      
 122 
     | 
    
         
            +
                  when 400..499
         
     | 
| 
      
 123 
     | 
    
         
            +
                    error_body = begin
         
     | 
| 
      
 124 
     | 
    
         
            +
                      JSON.parse(response.body)
         
     | 
| 
      
 125 
     | 
    
         
            +
                    rescue StandardError
         
     | 
| 
      
 126 
     | 
    
         
            +
                      { "error" => response.body }
         
     | 
| 
      
 127 
     | 
    
         
            +
                    end
         
     | 
| 
      
 128 
     | 
    
         
            +
                    raise APIError, "API client error (#{response.status}): #{error_body["error"]["message"] || "Unknown error"}"
         
     | 
| 
      
 129 
     | 
    
         
            +
                  when 500..599
         
     | 
| 
      
 130 
     | 
    
         
            +
                    raise APIError, "API server error (#{response.status}): The server encountered an error"
         
     | 
| 
      
 131 
     | 
    
         
            +
                  else
         
     | 
| 
      
 132 
     | 
    
         
            +
                    raise APIError, "Unknown API error (#{response.status})"
         
     | 
| 
      
 133 
     | 
    
         
            +
                  end
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                # Extract content from the response
         
     | 
| 
      
 137 
     | 
    
         
            +
                # @param response [Hash] Parsed API response
         
     | 
| 
      
 138 
     | 
    
         
            +
                # @return [String] The extracted content
         
     | 
| 
      
 139 
     | 
    
         
            +
                # @raise [GeminiCraft::ResponseError] If the response format is unexpected
         
     | 
| 
      
 140 
     | 
    
         
            +
                def extract_content(response)
         
     | 
| 
      
 141 
     | 
    
         
            +
                  candidates = response["candidates"]
         
     | 
| 
      
 142 
     | 
    
         
            +
                  return "" if candidates.nil? || candidates.empty?
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                  content = candidates[0]["content"]
         
     | 
| 
      
 145 
     | 
    
         
            +
                  return "" if content.nil?
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                  parts = content["parts"]
         
     | 
| 
      
 148 
     | 
    
         
            +
                  return "" if parts.nil? || parts.empty?
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                  text = parts[0]["text"]
         
     | 
| 
      
 151 
     | 
    
         
            +
                  text || ""
         
     | 
| 
      
 152 
     | 
    
         
            +
                rescue StandardError => e
         
     | 
| 
      
 153 
     | 
    
         
            +
                  raise ResponseError, "Failed to extract content from response: #{e.message}"
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                # Generate a cache key from request parameters
         
     | 
| 
      
 157 
     | 
    
         
            +
                # @param text [String] The text prompt
         
     | 
| 
      
 158 
     | 
    
         
            +
                # @param system_instruction [String, nil] Optional system instruction
         
     | 
| 
      
 159 
     | 
    
         
            +
                # @param options [Hash] Additional options
         
     | 
| 
      
 160 
     | 
    
         
            +
                # @return [String] A unique cache key
         
     | 
| 
      
 161 
     | 
    
         
            +
                def generate_cache_key(text, system_instruction, options)
         
     | 
| 
      
 162 
     | 
    
         
            +
                  key_parts = [
         
     | 
| 
      
 163 
     | 
    
         
            +
                    @config.model,
         
     | 
| 
      
 164 
     | 
    
         
            +
                    text,
         
     | 
| 
      
 165 
     | 
    
         
            +
                    system_instruction,
         
     | 
| 
      
 166 
     | 
    
         
            +
                    options.to_s
         
     | 
| 
      
 167 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                  # Create a deterministic string from the key parts
         
     | 
| 
      
 170 
     | 
    
         
            +
                  Digest::SHA256.hexdigest(key_parts.join("--"))
         
     | 
| 
      
 171 
     | 
    
         
            +
                end
         
     | 
| 
      
 172 
     | 
    
         
            +
              end
         
     | 
| 
      
 173 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GeminiCraft
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Configuration for the GeminiCraft gem
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Configuration
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_accessor :api_key, :api_base_url, :model, :timeout, :cache_enabled, :cache_ttl, :max_retries
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                # Initialize a new configuration with default values
         
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @api_key = ENV.fetch("GEMINI_API_KEY", nil)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @api_base_url = "https://generativelanguage.googleapis.com/v1beta"
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @model = "gemini-2.0-flash"
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @timeout = 30
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @cache_enabled = false
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @cache_ttl = 3600 # 1 hour in seconds
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @max_retries = 3
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                # Validate that the configuration has required parameters
         
     | 
| 
      
 20 
     | 
    
         
            +
                # @raise [GeminiCraft::ConfigurationError] if the configuration is invalid
         
     | 
| 
      
 21 
     | 
    
         
            +
                def validate!
         
     | 
| 
      
 22 
     | 
    
         
            +
                  raise ConfigurationError, "API key must be configured" unless api_key
         
     | 
| 
      
 23 
     | 
    
         
            +
                  raise ConfigurationError, "Model must be configured" unless model
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              # Error raised when configuration is invalid
         
     | 
| 
      
 28 
     | 
    
         
            +
              class ConfigurationError < Error; end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,12 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GeminiCraft
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Base error class for all GeminiCraft errors
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Error < StandardError; end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              # Error raised when there's an issue with API requests
         
     | 
| 
      
 8 
     | 
    
         
            +
              class APIError < Error; end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              # Error raised when the response cannot be processed
         
     | 
| 
      
 11 
     | 
    
         
            +
              class ResponseError < Error; end
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/gemini_craft/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: gemini_craft
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.1. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.2
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Shobhit Jain
         
     | 
| 
         @@ -158,19 +158,16 @@ executables: [] 
     | 
|
| 
       158 
158 
     | 
    
         
             
            extensions: []
         
     | 
| 
       159 
159 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       160 
160 
     | 
    
         
             
            files:
         
     | 
| 
       161 
     | 
    
         
            -
            - ".rspec"
         
     | 
| 
       162 
     | 
    
         
            -
            - ".rubocop.yml"
         
     | 
| 
       163 
161 
     | 
    
         
             
            - CHANGELOG.md
         
     | 
| 
       164 
162 
     | 
    
         
             
            - CODE_OF_CONDUCT.md
         
     | 
| 
       165 
     | 
    
         
            -
            - Gemfile
         
     | 
| 
       166 
163 
     | 
    
         
             
            - LICENSE.txt
         
     | 
| 
       167 
164 
     | 
    
         
             
            - README.md
         
     | 
| 
       168 
     | 
    
         
            -
            - Rakefile
         
     | 
| 
       169 
     | 
    
         
            -
            - bin/console
         
     | 
| 
       170 
     | 
    
         
            -
            - bin/setup
         
     | 
| 
       171 
165 
     | 
    
         
             
            - lib/gemini_craft.rb
         
     | 
| 
      
 166 
     | 
    
         
            +
            - lib/gemini_craft/cache.rb
         
     | 
| 
      
 167 
     | 
    
         
            +
            - lib/gemini_craft/client.rb
         
     | 
| 
      
 168 
     | 
    
         
            +
            - lib/gemini_craft/configuration.rb
         
     | 
| 
      
 169 
     | 
    
         
            +
            - lib/gemini_craft/error.rb
         
     | 
| 
       172 
170 
     | 
    
         
             
            - lib/gemini_craft/version.rb
         
     | 
| 
       173 
     | 
    
         
            -
            - sig/gemini_craft.rbs
         
     | 
| 
       174 
171 
     | 
    
         
             
            homepage: https://github.com/shobhits7/gemini_craft
         
     | 
| 
       175 
172 
     | 
    
         
             
            licenses:
         
     | 
| 
       176 
173 
     | 
    
         
             
            - MIT
         
     | 
| 
         @@ -178,6 +175,7 @@ metadata: 
     | 
|
| 
       178 
175 
     | 
    
         
             
              homepage_uri: https://github.com/shobhits7/gemini_craft
         
     | 
| 
       179 
176 
     | 
    
         
             
              source_code_uri: https://github.com/shobhits7/gemini_craft
         
     | 
| 
       180 
177 
     | 
    
         
             
              changelog_uri: https://github.com/shobhits7/gemini_craft/blob/main/CHANGELOG.md
         
     | 
| 
      
 178 
     | 
    
         
            +
              rubygems_mfa_required: 'true'
         
     | 
| 
       181 
179 
     | 
    
         
             
            post_install_message:
         
     | 
| 
       182 
180 
     | 
    
         
             
            rdoc_options: []
         
     | 
| 
       183 
181 
     | 
    
         
             
            require_paths:
         
     | 
    
        data/.rspec
    DELETED
    
    
    
        data/.rubocop.yml
    DELETED
    
    
    
        data/Gemfile
    DELETED
    
    
    
        data/Rakefile
    DELETED
    
    
    
        data/bin/console
    DELETED
    
    | 
         @@ -1,11 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            #!/usr/bin/env ruby
         
     | 
| 
       2 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
            require "bundler/setup"
         
     | 
| 
       5 
     | 
    
         
            -
            require "gemini_craft"
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
            # You can add fixtures and/or initialization code here to make experimenting
         
     | 
| 
       8 
     | 
    
         
            -
            # with your gem easier. You can also use a different console, if you like.
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
            require "irb"
         
     | 
| 
       11 
     | 
    
         
            -
            IRB.start(__FILE__)
         
     | 
    
        data/bin/setup
    DELETED
    
    
    
        data/sig/gemini_craft.rbs
    DELETED