n2b 0.2.2 → 0.2.4

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: 3a24dc543659153dabaf892f6bed38934425ac43a1a0b2a263e82c3913e0b5f9
4
- data.tar.gz: 01ccd36a76124d3599a7dd26a5cb1f443c4465e21c5cd12505512c00f771a164
3
+ metadata.gz: bf304be008b27bf4336085ec39f75fc8ac5207c6e17d442d5129a366795629eb
4
+ data.tar.gz: f436a7dc4a59f2840b023d7e406aa5fa2aa02dee7ebb10f48c982efaaf489546
5
5
  SHA512:
6
- metadata.gz: 737d3f29477d61da584640389552ebb01809fc762ec6348ee032ca0ab9fe6a3c2360df103fbe8daa3751a980b0b9c41b1998523c5f74f0b6ebb906e5a4a939dc
7
- data.tar.gz: 5e975752513f183640c391afd46bd322d80da3a488d046d3e7e487f496b96a65c6bc60fae47de4187e2ca455c41d3aa1a6f23acdd2095f2cccaa36cbacbe8427
6
+ metadata.gz: 770f49a5df340f3f9eae3f9072eafcbd9e8de6e2a5a227da3a96c67ebb22ca998411d1098921a375a9203fe446593ac8b15cfc3b6c6e6d13503a48957fed29c9
7
+ data.tar.gz: 88720e0bae3adf499830681214c142ea96787f3fbae01fcfe276593ce3860f65127783293cf2c1c993725747ad54165e260473f84d172fb290490165cd587708
data/README.md CHANGED
@@ -13,61 +13,74 @@ N2B (Natural Language to Bash & Ruby) is a Ruby gem that leverages AI to convert
13
13
 
14
14
  ## Installation
15
15
 
16
- Add this line to your application's Gemfile:
16
+ ```bash
17
+ gem install n2b
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### In IRB/Rails Console
23
+
24
+ First, require and extend the N2B module:
17
25
 
18
26
  ```ruby
19
- gem 'n2b'
27
+ require 'n2b'
28
+ extend N2B::IRB
20
29
  ```
21
30
 
22
- And then execute:
31
+ For automatic loading in every IRB session, add these lines to your `~/.irbrc`:
23
32
 
24
- ```bash
25
- $ bundle install
33
+ ```ruby
34
+ require 'n2b'
35
+ extend N2B::IRB
26
36
  ```
27
37
 
28
- Or install it yourself as:
38
+ After loading, you can use the following commands:
29
39
 
30
- ```bash
31
- $ gem install n2b
40
+ - `n2r` - For general Ruby assistance
41
+ - `n2rrbit` - For Errbit error analysis
42
+ - `n2rscrum` - For generating Scrum tickets
43
+
44
+ ### Examples
45
+
46
+ ```ruby
47
+ # Get help with a Ruby question
48
+ n2r "How do I parse JSON in Ruby?"
49
+
50
+ # Analyze an Errbit error
51
+ n2rrbit(url: "your_errbit_url", cookie: "your_cookie")
52
+
53
+ # Generate a Scrum ticket
54
+ n2rscrum "Create a user authentication system"
32
55
  ```
33
56
 
34
57
  ## Configuration
35
58
 
36
- Create a config file at `~/.n2b/config.yml` with your API keys:
59
+ Create a config file at `~/.n2b/config.yml` with your API keys. You can also use a custom config file by setting the `N2B_CONFIG_FILE` environment variable:
37
60
 
61
+ ```bash
62
+ export N2B_CONFIG_FILE=/path/to/your/config.yml
63
+ ```
64
+
65
+ Example config file:
38
66
  ```yaml
39
- llm: claude # or openai
67
+ llm: claude # or openai, gemini
40
68
  claude:
41
69
  key: your-anthropic-api-key
42
70
  model: claude-3-opus-20240229 # or opus, haiku, sonnet
43
71
  openai:
44
72
  key: your-openai-api-key
45
73
  model: gpt-4 # or gpt-3.5-turbo
74
+ gemini:
75
+ key: your-google-api-key
76
+ model: gemini-flash # uses gemini-2.0-flash model
46
77
  ```
47
78
 
48
- ## Usage
49
-
50
- ### Convert Natural Language to Bash
51
-
52
- ```ruby
53
- require 'n2b'
54
-
55
- # Convert a natural language instruction to a bash command
56
- N2B::Base.new.n2b("list all jpg files in the current directory")
57
- # => find . -name "*.jpg"
58
- ```
59
-
60
- ### Generate Ruby Code
61
-
62
- ```ruby
63
- require 'n2b'
64
-
65
- # In an IRB console
66
- n2r("create a function that calculates fibonacci numbers")
79
+ You can also set the history file location using the `N2B_HISTORY_FILE` environment variable:
80
+ ```bash
81
+ export N2B_HISTORY_FILE=/path/to/your/history
67
82
  ```
68
83
 
69
- This will output both the code and an explanation:
70
-
71
84
  ## Quick Example N2B
72
85
 
73
86
  ```
data/lib/n2b/base.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module N2B
2
2
  class Base
3
3
 
4
- CONFIG_FILE = File.expand_path('~/.n2b/config.yml')
5
- HISTORY_FILE = File.expand_path('~/.n2b/history')
4
+ CONFIG_FILE = ENV['N2B_CONFIG_FILE'] || File.expand_path('~/.n2b/config.yml')
5
+ HISTORY_FILE = ENV['N2B_HISTORY_FILE'] || File.expand_path('~/.n2b/history')
6
6
 
7
7
  def load_config
8
8
  if File.exist?(CONFIG_FILE)
@@ -18,16 +18,24 @@ module N2B
18
18
  model = config['model'] || 'sonnet35'
19
19
 
20
20
  if api_key.nil? || api_key == '' || reconfigure
21
- print "choose a language model to use (1:claude, 2:openai) #{ config['llm'] }: "
21
+ print "choose a language model to use (1:claude, 2:openai, 3:gemini) #{ config['llm'] }: "
22
22
  llm = $stdin.gets.chomp
23
23
  llm = config['llm'] if llm.empty?
24
- unless ['claude', 'openai','1','2'].include?(llm)
25
- puts "Invalid language model. Choose from: claude, openai"
24
+ unless ['claude', 'openai', 'gemini', '1', '2', '3'].include?(llm)
25
+ puts "Invalid language model. Choose from: claude, openai, gemini"
26
26
  exit 1
27
27
  end
28
28
  llm = 'claude' if llm == '1'
29
29
  llm = 'openai' if llm == '2'
30
- llm_class = llm == 'openai' ? N2M::Llm::OpenAi : N2M::Llm::Claude
30
+ llm = 'gemini' if llm == '3'
31
+ llm_class = case llm
32
+ when 'openai'
33
+ N2M::Llm::OpenAi
34
+ when 'gemini'
35
+ N2M::Llm::Gemini
36
+ else
37
+ N2M::Llm::Claude
38
+ end
31
39
 
32
40
  print "Enter your #{llm} API key: #{ api_key.nil? || api_key.empty? ? '' : '(leave blank to keep the current key '+api_key[0..10]+'...)' }"
33
41
  api_key = $stdin.gets.chomp
@@ -50,11 +58,8 @@ module N2B
50
58
  config['append_to_shell_history'] = false
51
59
  puts "Current configuration: #{config['privacy']}"
52
60
  FileUtils.mkdir_p(File.dirname(CONFIG_FILE)) unless File.exist?(File.dirname(CONFIG_FILE))
53
- File.open(CONFIG_FILE, 'w+') do |f|
54
- f.write(config.to_yaml )
55
- end
61
+ File.write(CONFIG_FILE, config.to_yaml)
56
62
  end
57
-
58
63
  config
59
64
  end
60
65
  end
data/lib/n2b/irb.rb CHANGED
@@ -17,7 +17,14 @@ module N2B
17
17
 
18
18
  def n2r(input_string='', files: [], exception: nil, log: false)
19
19
  config = N2B::Base.new.get_config
20
- llm = config['llm'] == 'openai' ? N2M::Llm::OpenAi.new(config) : N2M::Llm::Claude.new(config)
20
+ llm = case config['llm']
21
+ when 'openai'
22
+ N2M::Llm::OpenAi.new(config)
23
+ when 'gemini'
24
+ N2M::Llm::Gemini.new(config)
25
+ else
26
+ N2M::Llm::Claude.new(config)
27
+ end
21
28
  # detect if inside rails console
22
29
  console = case
23
30
  when defined?(Rails) && Rails.respond_to?(:application)
@@ -586,7 +593,14 @@ module N2B
586
593
 
587
594
  def analyze_error(error_info, related_files)
588
595
  config = N2B::Base.new.get_config
589
- llm = config['llm'] == 'openai' ? N2M::Llm::OpenAi.new(config) : N2M::Llm::Claude.new(config)
596
+ llm = case config['llm']
597
+ when 'openai'
598
+ N2M::Llm::OpenAi.new(config)
599
+ when 'gemini'
600
+ N2M::Llm::Gemini.new(config)
601
+ else
602
+ N2M::Llm::Claude.new(config)
603
+ end
590
604
 
591
605
  # Build file content section, showing context if available
592
606
  file_content_section = related_files.map do |file_path, content|
@@ -651,7 +665,14 @@ module N2B
651
665
 
652
666
  def generate_error_ticket(error_info, related_files = {}, url = nil)
653
667
  config = N2B::Base.new.get_config
654
- llm = config['llm'] == 'openai' ? N2M::Llm::OpenAi.new(config) : N2M::Llm::Claude.new(config)
668
+ llm = case config['llm']
669
+ when 'openai'
670
+ N2M::Llm::OpenAi.new(config)
671
+ when 'gemini'
672
+ N2M::Llm::Gemini.new(config)
673
+ else
674
+ N2M::Llm::Claude.new(config)
675
+ end
655
676
 
656
677
  # Build file content section, showing context if available
657
678
  file_content_section = related_files.map do |file_path, content|
@@ -2,7 +2,7 @@ module N2M
2
2
  module Llm
3
3
  class Claude
4
4
  API_URI = URI.parse('https://api.anthropic.com/v1/messages')
5
- MODELS = { 'haiku' => 'claude-3-haiku-20240307', 'sonnet' => 'claude-3-sonnet-20240229', 'sonnet35' => 'claude-3-5-sonnet-20240620' }
5
+ MODELS = { 'haiku' => 'claude-3-haiku-20240307', 'sonnet' => 'claude-3-sonnet-20240229', 'sonnet35' => 'claude-3-5-sonnet-20240620', "sonnet37" => "claude-3-7-sonnet-20250219" }
6
6
 
7
7
  def initialize(config)
8
8
  @config = config
@@ -0,0 +1,69 @@
1
+ require 'net/http'
2
+ require 'json'
3
+ require 'uri'
4
+
5
+ module N2M
6
+ module Llm
7
+ class Gemini
8
+ API_URI = URI.parse('https://generativelanguage.googleapis.com/v1beta/models')
9
+ MODELS = {
10
+ 'gemini-flash' => 'gemini-2.0-flash'
11
+ }
12
+
13
+ def initialize(config)
14
+ @config = config
15
+ end
16
+
17
+ def make_request(content)
18
+ model = MODELS[@config['model']] || 'gemini-flash'
19
+ uri = URI.parse("#{API_URI}/#{model}:generateContent?key=#{@config['access_key']}")
20
+
21
+ request = Net::HTTP::Post.new(uri)
22
+ request.content_type = 'application/json'
23
+
24
+ request.body = JSON.dump({
25
+ "contents" => [{
26
+ "parts" => [{
27
+ "text" => content
28
+ }]
29
+ }]
30
+ })
31
+
32
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
33
+ http.request(request)
34
+ end
35
+
36
+ # check for errors
37
+ if response.code != '200'
38
+ puts "Error: #{response.code} #{response.message}"
39
+ puts response.body
40
+ puts "Config: #{@config.inspect}"
41
+ exit 1
42
+ end
43
+
44
+ parsed_response = JSON.parse(response.body)
45
+ answer = parsed_response['candidates'].first['content']['parts'].first['text']
46
+
47
+ begin
48
+ # Try to parse as JSON if it looks like JSON
49
+ if answer.strip.start_with?('{') && answer.strip.end_with?('}')
50
+ answer = JSON.parse(answer)
51
+ else
52
+ # If not JSON, wrap it in our expected format
53
+ answer = {
54
+ 'explanation' => answer,
55
+ 'code' => nil
56
+ }
57
+ end
58
+ rescue JSON::ParserError
59
+ # If JSON parsing fails, wrap the text in our expected format
60
+ answer = {
61
+ 'explanation' => answer,
62
+ 'code' => nil
63
+ }
64
+ end
65
+ answer
66
+ end
67
+ end
68
+ end
69
+ end
data/lib/n2b/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # lib/n2b/version.rb
2
2
  module N2B
3
- VERSION = "0.2.2"
3
+ VERSION = "0.2.4"
4
4
  end
data/lib/n2b.rb CHANGED
@@ -8,6 +8,7 @@ require 'fileutils'
8
8
  require 'n2b/version'
9
9
  require 'n2b/llm/claude'
10
10
  require 'n2b/llm/open_ai'
11
+ require 'n2b/llm/gemini'
11
12
  require 'n2b/base'
12
13
  require 'n2b/cli'
13
14
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: n2b
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Nothegger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-20 00:00:00.000000000 Z
11
+ date: 2025-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -69,6 +69,7 @@ files:
69
69
  - lib/n2b/cli.rb
70
70
  - lib/n2b/irb.rb
71
71
  - lib/n2b/llm/claude.rb
72
+ - lib/n2b/llm/gemini.rb
72
73
  - lib/n2b/llm/open_ai.rb
73
74
  - lib/n2b/version.rb
74
75
  homepage: https://github.com/stefan-kp/n2b