n2b 0.5.0 → 0.7.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/README.md +374 -23
- data/bin/n2b-diff +5 -0
- data/bin/n2b-test-jira +17 -14
- data/lib/n2b/cli.rb +137 -72
- data/lib/n2b/jira_client.rb +430 -70
- data/lib/n2b/llm/claude.rb +6 -19
- data/lib/n2b/llm/gemini.rb +8 -7
- data/lib/n2b/llm/ollama.rb +1 -1
- data/lib/n2b/llm/open_ai.rb +26 -20
- data/lib/n2b/merge_cli.rb +694 -0
- data/lib/n2b/merge_conflict_parser.rb +70 -0
- data/lib/n2b/template_engine.rb +105 -0
- data/lib/n2b/templates/diff_json_instruction.txt +27 -0
- data/lib/n2b/templates/diff_system_prompt.txt +23 -0
- data/lib/n2b/templates/jira_comment.txt +67 -0
- data/lib/n2b/templates/merge_conflict_prompt.txt +20 -0
- data/lib/n2b/version.rb +1 -1
- data/lib/n2b.rb +3 -0
- metadata +34 -7
data/lib/n2b/llm/open_ai.rb
CHANGED
@@ -22,20 +22,23 @@ module N2M
|
|
22
22
|
model_name
|
23
23
|
end
|
24
24
|
|
25
|
-
def make_request(content)
|
25
|
+
def make_request(content, expect_json: true)
|
26
26
|
request = Net::HTTP::Post.new(API_URI)
|
27
27
|
request.content_type = 'application/json'
|
28
28
|
request['Authorization'] = "Bearer #{@config['access_key']}"
|
29
29
|
|
30
|
-
|
30
|
+
body_hash = {
|
31
31
|
"model" => get_model_name,
|
32
|
-
response_format: { type: 'json_object' },
|
33
32
|
"messages" => [
|
34
33
|
{
|
35
34
|
"role" => "user",
|
36
35
|
"content" => content
|
37
|
-
}
|
38
|
-
|
36
|
+
}
|
37
|
+
]
|
38
|
+
}
|
39
|
+
body_hash["response_format"] = { "type" => "json_object" } if expect_json
|
40
|
+
|
41
|
+
request.body = JSON.dump(body_hash)
|
39
42
|
|
40
43
|
response = Net::HTTP.start(API_URI.hostname, API_URI.port, use_ssl: true) do |http|
|
41
44
|
http.request(request)
|
@@ -46,34 +49,38 @@ module N2M
|
|
46
49
|
raise N2B::LlmApiError.new("LLM API Error: #{response.code} #{response.message} - #{response.body}")
|
47
50
|
end
|
48
51
|
answer = JSON.parse(response.body)['choices'].first['message']['content']
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
if expect_json
|
53
|
+
begin
|
54
|
+
# remove everything before the first { and after the last }
|
55
|
+
answer = answer.sub(/.*\{(.*)\}.*/m, '{\1}') unless answer.start_with?('{')
|
56
|
+
answer = JSON.parse(answer)
|
57
|
+
rescue JSON::ParserError
|
58
|
+
answer = { 'commands' => answer.split("\n"), explanation: answer }
|
59
|
+
end
|
55
60
|
end
|
56
61
|
answer
|
57
62
|
end
|
58
63
|
|
59
|
-
def analyze_code_diff(prompt_content)
|
64
|
+
def analyze_code_diff(prompt_content, expect_json: true)
|
60
65
|
# This method assumes prompt_content is the full, ready-to-send prompt
|
61
66
|
# including all instructions for the LLM (system message, diff, user additions, JSON format).
|
62
67
|
request = Net::HTTP::Post.new(API_URI)
|
63
68
|
request.content_type = 'application/json'
|
64
69
|
request['Authorization'] = "Bearer #{@config['access_key']}"
|
65
70
|
|
66
|
-
|
71
|
+
body_hash = {
|
67
72
|
"model" => get_model_name,
|
68
|
-
"response_format" => { "type" => "json_object" }, # Crucial for OpenAI to return JSON
|
69
73
|
"messages" => [
|
70
74
|
{
|
71
|
-
"role" => "user",
|
75
|
+
"role" => "user",
|
72
76
|
"content" => prompt_content
|
73
77
|
}
|
74
78
|
],
|
75
|
-
"max_tokens" => @config['max_tokens'] || 1500
|
76
|
-
}
|
79
|
+
"max_tokens" => @config['max_tokens'] || 1500
|
80
|
+
}
|
81
|
+
body_hash["response_format"] = { "type" => "json_object" } if expect_json
|
82
|
+
|
83
|
+
request.body = JSON.dump(body_hash)
|
77
84
|
|
78
85
|
response = Net::HTTP.start(API_URI.hostname, API_URI.port, use_ssl: true) do |http|
|
79
86
|
http.request(request)
|
@@ -83,9 +90,8 @@ module N2M
|
|
83
90
|
raise N2B::LlmApiError.new("LLM API Error: #{response.code} #{response.message} - #{response.body}")
|
84
91
|
end
|
85
92
|
|
86
|
-
|
87
|
-
|
88
|
-
JSON.parse(response.body)['choices'].first['message']['content']
|
93
|
+
answer = JSON.parse(response.body)['choices'].first['message']['content']
|
94
|
+
answer
|
89
95
|
end
|
90
96
|
end
|
91
97
|
end
|