9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
# File 'lib/n2b/irb.rb', line 9
def n2r(input_string='', files: [], exception: nil, log: false)
config = N2B::Base.new.get_config
llm = config['llm'] == 'openai' ? N2M::Llm::OpenAi.new(config) : N2M::Llm::Claude.new(config)
console = case
when defined?(Rails)
"You are in a Rails console"
when defined?(IRB)
"You are in an IRB console"
else
"You are in a standard Ruby console"
end
get_defined_classes = ObjectSpace.each_object(Class).to_a
get_gemfile = File.read('Gemfile') if File.exist?('Gemfile')
source_files = []
input_string.scan(/[\w\/.-]+\.rb(?=\s|:|$)/).each do |file|
full_path = File.expand_path(file) source_files << full_path if File.exist?(full_path)
end
if exception
source_files += exception.backtrace.map do |line|
line.split(':').first
end
input_string << ' ' << exception.message << "\m" << exception.backtrace.join(' ')
end
source_files = source_files.sort_by do |file|
if file.start_with?(Dir.pwd)
0 else
1 end
end
file_content = (files+source_files[0..MAX_SOURCE_FILES-1]).inject({}) do |h,file|
h[file] = File.read(file) if File.exist?(file)
h
end
content = <<~HEREDOC
you are a professional ruby programmer
#{ console}
The following classes are defined in this session:
#{ get_defined_classes}
#{ get_gemfile }
#{ @n2r_answers ? "user have made #{@n2r_answers} before" : "" }
your task is to give the user guidance on how perform a task he is asking for
if he pasts an error or backtrace, you can provide a solution to the problem.
if you need files you can ask the user to provide them request.
he can send them with n2r "his question" files: ['file1.rb', 'file2.rb']
if he sends files and you mention them in the response, provide the file name of the snippets you are referring to.
answer in a valid json object with the key 'code' with only the ruby code to be executed and a key 'explanation' with a markdown string with the explanation and the code.
{ "code": "puts 'Hello, World!'", "explanation": "### Explanation \n This command ´´´puts 'Hello, world!'´´´ prints 'Hello, World!' to the terminal.", files: ['file1.rb', 'file2.rb']}
#{input_string}
#{ "the user provided the following files: #{ file_content.collect{|k,v| "#{k}:#{v}" }.join("\n") }" if file_content }
}}
HEREDOC
if log
log_file_path = File.expand_path('~/.n2b/n2r.log')
File.open(log_file_path, 'a') do |file|
file.puts(content)
end
end
@n2r_answers ||= []
@n2r_answer = llm.make_request(content)
@n2r_answers << { input: input_string, output: @n2r_answer }
@n2r_answer['code'].split("\n").each do |line|
puts line
end if @n2r_answer['code']
@n2r_answer['explanation'].split("\n").each do |line|
puts line
end
nil
end
|