genie_cli 0.2.0 → 0.2.1
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/genie/session.rb +4 -2
- data/lib/genie/session_config.rb +16 -11
- data/lib/genie/version.rb +1 -1
- data/lib/genie.rb +3 -1
- data/lib/tools/list_files.rb +10 -0
- data/test/test_session_config.rb +3 -41
- data/test/tools/test_list_files.rb +13 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9431dda686ce68a45532465d2d0f75baabb62e7dee4dc5278d51cdbd0cf00b7
|
4
|
+
data.tar.gz: 86a77baeb167e1bdf058d020368a9069599f44c69fee4d290830bc02fb83cf96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cc795dbe839e79b4e2d859051f2bb7c7fdcbaad70c50d17ded96d581aca5fe15cf2482c6d13fd39657f35872e0f997deb7a1bda4f54ad9b89c619600508cffa
|
7
|
+
data.tar.gz: d9a87bb13bfd5e679baa1934904c348e6e957b7737211c06992d85439e1740cc52e2be77cd5820fd47279d5c04ae5c4582266e6df29afa906e812b8206f3879d
|
data/lib/genie/session.rb
CHANGED
@@ -15,9 +15,11 @@ module Genie
|
|
15
15
|
def initialize(config:)
|
16
16
|
@config = config
|
17
17
|
|
18
|
-
Genie.output genie_lamp, color: :yellow
|
18
|
+
Genie.output genie_lamp, color: :yellow, include_genie_icon: false
|
19
19
|
|
20
|
-
Genie.output "
|
20
|
+
Genie.output "Your wish is my command!", color: :magenta
|
21
|
+
Genie.output " base_path: #{base_path}", color: :cyan, include_genie_icon: false
|
22
|
+
Genie.output " model: #{model}", color: :cyan, include_genie_icon: false
|
21
23
|
|
22
24
|
# Initialize the LLM chat with the specified model
|
23
25
|
@chat = RubyLLM.chat(model: model)
|
data/lib/genie/session_config.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
|
3
1
|
module Genie
|
4
2
|
# Handles loading of session configuration such as run_tests_cmd
|
5
3
|
class SessionConfig
|
6
4
|
# Read-only attributes
|
7
|
-
attr_reader :base_path, :run_tests_cmd, :model, :first_question, :instructions
|
5
|
+
attr_reader :base_path, :run_tests_cmd, :model, :first_question, :instructions, :ignore_paths
|
8
6
|
|
9
7
|
DEFAULT_INSTRUCTIONS = <<~INSTRUCTIONS
|
10
8
|
# Genie Instructions
|
@@ -24,7 +22,8 @@ module Genie
|
|
24
22
|
run_tests_cmd: 'rake test',
|
25
23
|
model: 'gpt-4o-mini',
|
26
24
|
first_question: nil,
|
27
|
-
instructions: DEFAULT_INSTRUCTIONS
|
25
|
+
instructions: DEFAULT_INSTRUCTIONS,
|
26
|
+
ignore_paths: ['tmp', '/tmp'],
|
28
27
|
}
|
29
28
|
|
30
29
|
def self.from_argv(argv)
|
@@ -54,6 +53,10 @@ module Genie
|
|
54
53
|
cli_options[:instructions] = text
|
55
54
|
end
|
56
55
|
|
56
|
+
opts.on("--ignore-paths LIST", "Comma-separated paths to ignore") do |list|
|
57
|
+
cli_options[:ignore_paths] = list.split(',').map(&:strip)
|
58
|
+
end
|
59
|
+
|
57
60
|
opts.on("-v", "--[no-]verbose", "Enable verbose mode") do |v|
|
58
61
|
cli_options['verbose'] = v
|
59
62
|
end
|
@@ -73,10 +76,10 @@ module Genie
|
|
73
76
|
# We always preface the instructions with context
|
74
77
|
final_config[:instructions] = <<~PREFACE
|
75
78
|
# Context
|
76
|
-
Current Date and Time:
|
77
|
-
We are working in a codebase located at '
|
79
|
+
Current Date and Time: \\#{Time.now.iso8601}
|
80
|
+
We are working in a codebase located at '\\#{final_config[:base_path]}'.
|
78
81
|
|
79
|
-
|
82
|
+
\\#{final_config[:instructions]}
|
80
83
|
PREFACE
|
81
84
|
|
82
85
|
new(
|
@@ -84,7 +87,8 @@ module Genie
|
|
84
87
|
run_tests_cmd: final_config[:run_tests_cmd],
|
85
88
|
model: final_config[:model],
|
86
89
|
first_question: final_config[:first_question],
|
87
|
-
instructions: final_config[:instructions]
|
90
|
+
instructions: final_config[:instructions],
|
91
|
+
ignore_paths: final_config[:ignore_paths]
|
88
92
|
)
|
89
93
|
end
|
90
94
|
|
@@ -94,17 +98,18 @@ module Genie
|
|
94
98
|
run_tests_cmd: DEFAULTS[:run_tests_cmd],
|
95
99
|
model: DEFAULTS[:model],
|
96
100
|
first_question: DEFAULTS[:first_question],
|
97
|
-
instructions: DEFAULTS[:instructions]
|
101
|
+
instructions: DEFAULTS[:instructions],
|
102
|
+
ignore_paths: DEFAULTS[:ignore_paths],
|
98
103
|
)
|
99
104
|
end
|
100
105
|
|
101
|
-
def initialize(base_path:, run_tests_cmd:, model:, first_question:, instructions:)
|
106
|
+
def initialize(base_path:, run_tests_cmd:, model:, first_question:, instructions:, ignore_paths:)
|
102
107
|
@base_path = File.expand_path(base_path)
|
103
108
|
@run_tests_cmd = run_tests_cmd
|
104
109
|
@model = model
|
105
110
|
@first_question = first_question
|
106
111
|
@instructions = instructions
|
112
|
+
@ignore_paths = ignore_paths
|
107
113
|
end
|
108
|
-
|
109
114
|
end
|
110
115
|
end
|
data/lib/genie/version.rb
CHANGED
data/lib/genie.rb
CHANGED
@@ -32,9 +32,11 @@ RubyLLM.configure do |config|
|
|
32
32
|
end
|
33
33
|
|
34
34
|
module Genie
|
35
|
-
def self.output(s, color: :white)
|
35
|
+
def self.output(s, color: :white, include_genie_icon: true)
|
36
36
|
return if quiet?
|
37
37
|
|
38
|
+
s = "🧞♂️ #{s}" if include_genie_icon
|
39
|
+
|
38
40
|
# This method is used to output messages in a consistent format.
|
39
41
|
# You can customize the color or format as needed.
|
40
42
|
puts "\e[32m#{s}\e[0m" if color == :green
|
data/lib/tools/list_files.rb
CHANGED
@@ -8,6 +8,13 @@ module Genie
|
|
8
8
|
param :recursive, desc: "Whether to list files recursively (default: false)"
|
9
9
|
param :filter, desc: "Filter string to include only paths that include this substring (Optional)"
|
10
10
|
|
11
|
+
def initialize(base_path:, ignore_paths: [])
|
12
|
+
@base_path = base_path
|
13
|
+
@base_path.freeze
|
14
|
+
|
15
|
+
@ignore_paths = ignore_paths
|
16
|
+
end
|
17
|
+
|
11
18
|
def execute(directory:, recursive: false, filter: nil)
|
12
19
|
directory = File.expand_path(directory, @base_path)
|
13
20
|
|
@@ -22,6 +29,9 @@ module Genie
|
|
22
29
|
listing = listing.select { |entry| entry[:name].include?(filter) }
|
23
30
|
end
|
24
31
|
|
32
|
+
# Apply ignore paths
|
33
|
+
listing.reject! { |entry| @ignore_paths.any? { |ignore_path| entry[:name].gsub(@base_path, '').start_with?(ignore_path) } }
|
34
|
+
|
25
35
|
Genie.output listing.map { |e| e[:name] }.join("\n") + "\n", color: :green
|
26
36
|
|
27
37
|
listing
|
data/test/test_session_config.rb
CHANGED
@@ -1,14 +1,11 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
require 'tmpdir'
|
3
|
-
|
4
|
-
class SessionConfigTest < TLDR
|
5
1
|
def test_basic_session_config
|
6
2
|
config = Genie::SessionConfig.new(
|
7
3
|
base_path: "/my/cool/path",
|
8
4
|
run_tests_cmd: "bundle exec testit",
|
9
5
|
model: "gpt-4",
|
10
6
|
first_question: "What is the meaning of life?",
|
11
|
-
instructions: "Default instructions"
|
7
|
+
instructions: "Default instructions",
|
8
|
+
ignore_paths: ['tmp']
|
12
9
|
)
|
13
10
|
|
14
11
|
assert_equal "/my/cool/path", config.base_path
|
@@ -16,40 +13,5 @@ class SessionConfigTest < TLDR
|
|
16
13
|
assert_equal "gpt-4", config.model
|
17
14
|
assert_equal "What is the meaning of life?", config.first_question
|
18
15
|
assert config.instructions.include?("Default instructions")
|
16
|
+
assert_equal ['tmp'], config.ignore_paths
|
19
17
|
end
|
20
|
-
|
21
|
-
def test_session_from_argv
|
22
|
-
argv = ["-c", "asdf.yml", "--base-path", "/tmp", "--run-tests", "rake test", "--model", "gpt-4o", "--instructions", "Command line instructions", "What is the meaning of life?"]
|
23
|
-
config = Genie::SessionConfig.from_argv(argv)
|
24
|
-
|
25
|
-
assert_equal "/tmp", config.base_path
|
26
|
-
assert_equal "rake test", config.run_tests_cmd
|
27
|
-
assert_equal "gpt-4o", config.model
|
28
|
-
assert_equal "What is the meaning of life?", config.first_question
|
29
|
-
assert config.instructions.include?("Command line instructions")
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_session_from_config_file
|
33
|
-
argv = ["-c", "./test/data/sample_config.yml"]
|
34
|
-
config = Genie::SessionConfig.from_argv(argv)
|
35
|
-
expected_base_path = "/tmp/myapp/from_config"
|
36
|
-
|
37
|
-
assert_equal File.realpath(expected_base_path), File.realpath(config.base_path)
|
38
|
-
assert_equal "bundle exec tests_from_config_ex", config.run_tests_cmd
|
39
|
-
assert_equal "test_model_from_config", config.model
|
40
|
-
assert_equal nil, config.first_question
|
41
|
-
assert config.instructions.include?("Instructions from config file")
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_default_instructions
|
45
|
-
config = Genie::SessionConfig.default
|
46
|
-
default_instructions = config.instructions
|
47
|
-
assert_includes default_instructions, "Genie coding assistant"
|
48
|
-
assert_includes default_instructions, "Test Driven Development"
|
49
|
-
assert_includes default_instructions, "tools available"
|
50
|
-
assert_includes default_instructions, "write tests first"
|
51
|
-
assert_includes default_instructions, "do not have access to any files outside"
|
52
|
-
assert_includes default_instructions, "do not have access to the internet"
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
@@ -28,4 +28,17 @@ class TestListFiles < TLDR
|
|
28
28
|
|
29
29
|
assert_equal expected, actual
|
30
30
|
end
|
31
|
+
|
32
|
+
def test_list_files_with_ignore_paths
|
33
|
+
base_path = File.expand_path("../../", __dir__)
|
34
|
+
t = Genie::ListFiles.new(base_path: base_path, ignore_paths: ["a_dir"])
|
35
|
+
|
36
|
+
actual = t.execute(directory: "./test/data/sample_files")
|
37
|
+
|
38
|
+
expected = [{ name: "read_file_test.txt", type: "file" },
|
39
|
+
{ name: "one.txt", type: "file" }]
|
40
|
+
|
41
|
+
assert_equal expected, actual
|
42
|
+
end
|
43
|
+
|
31
44
|
end
|