gemini-ai 1.0.0

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.
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'event_stream_parser'
4
+ require 'faraday'
5
+ require 'json'
6
+ require 'googleauth'
7
+
8
+ module Gemini
9
+ module Controllers
10
+ class Client
11
+ def initialize(config)
12
+ @authorizer = ::Google::Auth::ServiceAccountCredentials.make_creds(
13
+ json_key_io: File.open(config[:credentials][:file_path]),
14
+ scope: 'https://www.googleapis.com/auth/cloud-platform'
15
+ )
16
+
17
+ @address = "https://#{config[:credentials][:region]}-aiplatform.googleapis.com/v1/projects/#{config[:credentials][:project_id]}/locations/#{config[:credentials][:region]}/publishers/google/models/#{config[:settings][:model]}"
18
+
19
+ @stream = config[:settings][:stream]
20
+ end
21
+
22
+ def stream_generate_content(payload, stream: nil, &callback)
23
+ request('streamGenerateContent', payload, stream:, &callback)
24
+ end
25
+
26
+ def request(path, payload, stream: nil, &callback)
27
+ stream_enabled = stream.nil? ? @stream : stream
28
+ url = "#{@address}:#{path}"
29
+ url += '?alt=sse' if stream_enabled
30
+
31
+ if !callback.nil? && !stream_enabled
32
+ raise StandardError, 'You are trying to use a block without stream enabled."'
33
+ end
34
+
35
+ results = []
36
+
37
+ response = Faraday.new.post do |request|
38
+ request.url url
39
+ request.headers['Content-Type'] = 'application/json'
40
+ request.headers['Authorization'] = "Bearer #{@authorizer.fetch_access_token!['access_token']}"
41
+ request.body = payload.to_json
42
+
43
+ if stream_enabled
44
+ parser = EventStreamParser::Parser.new
45
+
46
+ request.options.on_data = proc do |chunk, bytes, env|
47
+ if env && env.status != 200
48
+ raise_error = Faraday::Response::RaiseError.new
49
+ raise_error.on_complete(env.merge(body: chunk))
50
+ end
51
+
52
+ parser.feed(chunk) do |type, data, id, reconnection_time|
53
+ parsed_data = safe_parse_json(data)
54
+ result = {
55
+ event: safe_parse_json(data),
56
+ parsed: { type:, data:, id:, reconnection_time: },
57
+ raw: { chunk:, bytes:, env: }
58
+ }
59
+
60
+ callback.call(result[:event], result[:parsed], result[:raw]) unless callback.nil?
61
+
62
+ results << result
63
+
64
+ parsed_data['candidates'].find do |candidate|
65
+ !candidate['finishReason'].nil? && candidate['finishReason'] != ''
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ return safe_parse_json(response.body) unless stream_enabled
73
+
74
+ results.map { |result| result[:event] }
75
+ end
76
+
77
+ def safe_parse_json(raw)
78
+ raw.start_with?('{', '[') ? JSON.parse(raw) : raw
79
+ rescue JSON::ParserError
80
+ raw
81
+ end
82
+ end
83
+ end
84
+ end
data/gemini-ai.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'static/gem'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = Gemini::GEM[:name]
7
+ spec.version = Gemini::GEM[:version]
8
+ spec.authors = [Gemini::GEM[:author]]
9
+
10
+ spec.summary = Gemini::GEM[:summary]
11
+ spec.description = Gemini::GEM[:description]
12
+
13
+ spec.homepage = Gemini::GEM[:github]
14
+
15
+ spec.license = Gemini::GEM[:license]
16
+
17
+ spec.required_ruby_version = Gem::Requirement.new(">= #{Gemini::GEM[:ruby]}")
18
+
19
+ spec.metadata['allowed_push_host'] = Gemini::GEM[:gem_server]
20
+
21
+ spec.metadata['homepage_uri'] = spec.homepage
22
+ spec.metadata['source_code_uri'] = Gemini::GEM[:github]
23
+
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{\A(?:test|spec|features)/})
27
+ end
28
+ end
29
+
30
+ spec.require_paths = ['ports/dsl']
31
+
32
+ spec.add_dependency 'event_stream_parser', '~> 1.0'
33
+ spec.add_dependency 'faraday', '~> 2.7', '>= 2.7.12'
34
+ spec.add_dependency 'googleauth', '~> 1.9', '>= 1.9.1'
35
+
36
+ spec.metadata['rubygems_mfa_required'] = 'true'
37
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../static/gem'
4
+ require_relative '../../controllers/client'
5
+
6
+ module Gemini
7
+ def self.new(...)
8
+ Controllers::Client.new(...)
9
+ end
10
+
11
+ def self.version
12
+ Gemini::GEM[:version]
13
+ end
14
+ end
data/static/gem.rb ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gemini
4
+ GEM = {
5
+ name: 'gemini-ai',
6
+ version: '1.0.0',
7
+ author: 'gbaptista',
8
+ summary: "Interact with Google's Gemini AI.",
9
+ description: "A Ruby Gem for interacting with Gemini through Vertex AI, Google's generative AI service.",
10
+ github: 'https://github.com/gbaptista/gemini-ai',
11
+ gem_server: 'https://rubygems.org',
12
+ license: 'MIT',
13
+ ruby: '3.1.0'
14
+ }.freeze
15
+ end
@@ -0,0 +1,39 @@
1
+ (require '[clojure.string :as str])
2
+
3
+ (defn slugify [text]
4
+ (-> text
5
+ (clojure.string/lower-case)
6
+ (clojure.string/replace " " "-")
7
+ (clojure.string/replace #"[^a-z0-9\-]" "")))
8
+
9
+ (defn remove-code-blocks [content]
10
+ (let [code-block-regex #"(?s)```.*?```"]
11
+ (clojure.string/replace content code-block-regex "")))
12
+
13
+ (defn process-line [line]
14
+ (when-let [[_ hashes title] (re-find #"^(\#{2,}) (.+)" line)]
15
+ (let [link (slugify title)]
16
+ {:level (count hashes) :title title :link link})))
17
+
18
+ (defn create-index [content]
19
+ (let [processed-content (remove-code-blocks content)
20
+ processed-lines (->> processed-content
21
+ clojure.string/split-lines
22
+ (map process-line)
23
+ (remove nil?))]
24
+ (->> processed-lines
25
+ (map (fn [{:keys [level title link]}]
26
+ (str (apply str (repeat (* 4 (- level 2)) " "))
27
+ "- ["
28
+ title
29
+ "](#"
30
+ link
31
+ ")")))
32
+ (clojure.string/join "\n"))))
33
+
34
+
35
+ (let [content (slurp "template.md")
36
+ index (create-index content)
37
+ updated-content (clojure.string/replace content "{index}" index)]
38
+ (spit "README.md" updated-content)
39
+ (println "README.md successfully generated."))