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.
@@ -0,0 +1,70 @@
1
+ module N2B
2
+ # Parses files containing Git or Mercurial merge conflict markers.
3
+ # Returns an array of ConflictBlock objects with context information.
4
+ class MergeConflictParser
5
+ ConflictBlock = Struct.new(
6
+ :start_line, :end_line,
7
+ :base_content, :incoming_content,
8
+ :context_before, :context_after,
9
+ :base_label, :incoming_label,
10
+ keyword_init: true
11
+ )
12
+
13
+ DEFAULT_CONTEXT_LINES = 10
14
+
15
+ def initialize(context_lines: DEFAULT_CONTEXT_LINES)
16
+ @context_lines = context_lines
17
+ end
18
+
19
+ def parse(file_path)
20
+ raise ArgumentError, "File not found: #{file_path}" unless File.exist?(file_path)
21
+
22
+ lines = File.readlines(file_path, chomp: true)
23
+ blocks = []
24
+ i = 0
25
+ while i < lines.length
26
+ line = lines[i]
27
+ unless line.start_with?('<<<<<<<')
28
+ i += 1
29
+ next
30
+ end
31
+
32
+ start_line = i + 1
33
+ base_label = line.sub('<<<<<<<', '').strip
34
+ i += 1
35
+ base_lines = []
36
+ while i < lines.length && !lines[i].start_with?('=======')
37
+ base_lines << lines[i]
38
+ i += 1
39
+ end
40
+ i += 1 # skip ======= line
41
+ incoming_lines = []
42
+ while i < lines.length && !lines[i].start_with?('>>>>>>>')
43
+ incoming_lines << lines[i]
44
+ i += 1
45
+ end
46
+ incoming_label = lines[i].sub('>>>>>>>', '').strip if i < lines.length
47
+ end_line = i + 1
48
+
49
+ context_before_start = [start_line - @context_lines - 1, 0].max
50
+ context_before = lines[context_before_start...(start_line - 1)].join("\n")
51
+ context_after_end = [end_line + @context_lines - 1, lines.length - 1].min
52
+ context_after = lines[(end_line)..context_after_end].join("\n")
53
+
54
+ blocks << ConflictBlock.new(
55
+ start_line: start_line,
56
+ end_line: end_line,
57
+ base_content: base_lines.join("\n"),
58
+ incoming_content: incoming_lines.join("\n"),
59
+ context_before: context_before,
60
+ context_after: context_after,
61
+ base_label: base_label,
62
+ incoming_label: incoming_label
63
+ )
64
+ i += 1
65
+ end
66
+
67
+ blocks
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,105 @@
1
+ module N2B
2
+ class TemplateEngine
3
+ def initialize(template, data)
4
+ @template = template
5
+ @data = data
6
+ end
7
+
8
+ def render
9
+ result = @template.dup
10
+
11
+ # Process loops first (they can contain variables)
12
+ result = process_loops(result)
13
+
14
+ # Process conditionals
15
+ result = process_conditionals(result)
16
+
17
+ # Process simple variables
18
+ result = process_variables(result)
19
+
20
+ result
21
+ end
22
+
23
+ private
24
+
25
+ def process_loops(content)
26
+ # Match {#each array_name} ... {/each}
27
+ content.gsub(/\{#each\s+(\w+)\}(.*?)\{\/each\}/m) do |match|
28
+ array_name = $1
29
+ loop_content = $2
30
+ array_data = @data[array_name] || @data[array_name.to_sym] || []
31
+
32
+ if array_data.is_a?(Array)
33
+ array_data.map do |item|
34
+ item_content = loop_content.dup
35
+
36
+ # Process conditionals within the loop context
37
+ if item.is_a?(Hash)
38
+ # Create temporary data context with item data
39
+ temp_data = @data.merge(item)
40
+ temp_engine = TemplateEngine.new(item_content, temp_data)
41
+ item_content = temp_engine.send(:process_conditionals, item_content)
42
+
43
+ # Replace item variables like {description}, {file_reference}
44
+ item.each do |key, value|
45
+ item_content.gsub!(/\{#{key}\}/, value.to_s)
46
+ end
47
+ else
48
+ # If item is a string, replace {.} with the item itself
49
+ item_content.gsub!(/\{\.?\}/, item.to_s)
50
+ end
51
+
52
+ item_content
53
+ end.join("")
54
+ else
55
+ ""
56
+ end
57
+ end
58
+ end
59
+
60
+ def process_conditionals(content)
61
+ # Match {#if condition} ... {#else} ... {/if} or {#if condition} ... {/if}
62
+ content.gsub(/\{#if\s+(.+?)\}(.*?)(?:\{#else\}(.*?))?\{\/if\}/m) do |match|
63
+ condition = $1.strip
64
+ if_content = $2
65
+ else_content = $3 || ""
66
+
67
+ if evaluate_condition(condition)
68
+ if_content
69
+ else
70
+ else_content
71
+ end
72
+ end
73
+ end
74
+
75
+ def process_variables(content)
76
+ # Replace {variable_name} with actual values
77
+ content.gsub(/\{(\w+)\}/) do |match|
78
+ var_name = $1
79
+ value = @data[var_name] || @data[var_name.to_sym]
80
+ value.to_s
81
+ end
82
+ end
83
+
84
+ def evaluate_condition(condition)
85
+ # Handle conditions like: status == 'IMPLEMENTED'
86
+ if condition.match(/(\w+)\s*(==|!=)\s*['"]([^'"]+)['"]/)
87
+ var_name = $1
88
+ operator = $2
89
+ expected_value = $3
90
+ actual_value = @data[var_name] || @data[var_name.to_sym]
91
+
92
+ case operator
93
+ when '=='
94
+ actual_value.to_s == expected_value
95
+ when '!='
96
+ actual_value.to_s != expected_value
97
+ end
98
+ else
99
+ # Simple boolean check
100
+ var_value = @data[condition] || @data[condition.to_sym]
101
+ !!var_value
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,27 @@
1
+ CRITICAL: Return ONLY a valid JSON object.
2
+ Do not include any explanatory text before or after the JSON.
3
+ Each error and improvement should include specific file paths and line numbers.
4
+
5
+ The JSON object must contain the following keys:
6
+ - "summary": (string) Brief overall description of the changes.
7
+ - "ticket_implementation_summary": (string) A concise summary of what was implemented or achieved in relation to the ticket's goals, based *only* on the provided diff. This is for developer status updates and Jira comments.
8
+ - "errors": (list of strings) Potential bugs or issues found.
9
+ - "improvements": (list of strings) Suggestions for code quality, style, performance, or security.
10
+ - "test_coverage": (string) Assessment of test coverage for the changes.
11
+ - "requirements_evaluation": (string, include only if requirements were provided in the prompt) Evaluation of how the changes meet the provided requirements.
12
+
13
+ Example format:
14
+ {
15
+ "summary": "Refactored the user authentication module and added password complexity checks.",
16
+ "ticket_implementation_summary": "Implemented the core logic for user password updates and strengthened security by adding complexity validation as per the ticket's primary goal. Some UI elements are pending.",
17
+ "errors": [
18
+ "lib/example.rb line 42: Potential null pointer exception when accessing user.name without checking if user is nil.",
19
+ "src/main.js lines 15-20: Missing error handling for async operation."
20
+ ],
21
+ "improvements": [
22
+ "lib/example.rb line 30: Consider using a constant for the magic number 42.",
23
+ "src/utils.py lines 5-10: This method could be simplified using list comprehension."
24
+ ],
25
+ "test_coverage": "Good: New functionality in lib/example.rb has corresponding tests in test/example_test.rb. Missing: No tests for error handling edge cases in the new validation method.",
26
+ "requirements_evaluation": "✅ IMPLEMENTED: User authentication feature is fully implemented in auth.rb. ⚠️ PARTIALLY IMPLEMENTED: Error handling is present but lacks specific error codes. ❌ NOT IMPLEMENTED: Email notifications are not addressed in this diff."
27
+ }
@@ -0,0 +1,23 @@
1
+ You are a senior software developer reviewing a code diff.
2
+ Your task is to provide a constructive and detailed analysis of the changes.
3
+ Focus on identifying potential bugs, suggesting improvements in code quality, style, performance, and security.
4
+ Also, provide a concise summary of the changes.
5
+
6
+ IMPORTANT: When referring to specific issues or improvements, always include:
7
+ - The exact file path (e.g., "lib/n2b/cli.rb")
8
+ - The specific line numbers or line ranges (e.g., "line 42" or "lines 15-20")
9
+ - The exact code snippet you're referring to when possible
10
+
11
+ This helps users quickly locate and understand the issues you identify.
12
+
13
+ SPECIAL FOCUS ON TEST COVERAGE:
14
+ Pay special attention to whether the developer has provided adequate test coverage for the changes:
15
+ - Look for new test files or modifications to existing test files
16
+ - Check if new functionality has corresponding tests
17
+ - Evaluate if edge cases and error conditions are tested
18
+ - Assess if the tests are meaningful and comprehensive
19
+ - Note any missing test coverage that should be added
20
+
21
+ NOTE: In addition to the diff, you will also receive the current code context around the changed areas.
22
+ This provides better understanding of the surrounding code and helps with more accurate analysis.
23
+ The user may provide additional instructions or specific requirements below.
@@ -0,0 +1,67 @@
1
+ *N2B Code Analysis Report*
2
+ =========================
3
+
4
+ *Implementation Summary:*
5
+ {implementation_summary}
6
+
7
+ ---
8
+
9
+ *Automated Analysis Findings:*
10
+
11
+ {expand:🚨 Critical Issues (Must Fix Before Merge)}
12
+ {#each critical_errors}
13
+ ☐ {file_reference} - {description}
14
+ {/each}
15
+ {#if critical_errors_empty}
16
+ ✅ No critical issues found
17
+ {/if}
18
+ {expand}
19
+
20
+ {expand:⚠️ Important Issues (Should Address)}
21
+ {#each important_errors}
22
+ ☐ {file_reference} - {description}
23
+ {/each}
24
+ {#if important_errors_empty}
25
+ ✅ No important issues found
26
+ {/if}
27
+ {expand}
28
+
29
+ {expand:💡 Suggested Improvements (Nice to Have)}
30
+ {#each improvements}
31
+ ☐ {file_reference} - {description}
32
+ {/each}
33
+ {#if improvements_empty}
34
+ ℹ️ No specific improvements suggested
35
+ {/if}
36
+ {expand}
37
+
38
+ {expand:🧪 Test Coverage Assessment}
39
+ *Overall Assessment:* {test_coverage_summary}
40
+
41
+ *Missing Test Coverage:*
42
+ {#each missing_tests}
43
+ ☐ {description}
44
+ {/each}
45
+ {#if missing_tests_empty}
46
+ ✅ Test coverage appears adequate
47
+ {/if}
48
+ {expand}
49
+
50
+ *📋 Requirements Evaluation:*
51
+ {#each requirements}
52
+ {#if status == 'IMPLEMENTED'}
53
+ ☑ ✅ *IMPLEMENTED:* {description}
54
+ {/if}
55
+ {#if status == 'PARTIALLY_IMPLEMENTED'}
56
+ ☐ ⚠️ *PARTIALLY IMPLEMENTED:* {description}
57
+ {/if}
58
+ {#if status == 'NOT_IMPLEMENTED'}
59
+ ☐ ❌ *NOT IMPLEMENTED:* {description}
60
+ {/if}
61
+ {#if status == 'UNCLEAR'}
62
+ ☐ 🔍 *UNCLEAR:* {description}
63
+ {/if}
64
+ {/each}
65
+
66
+ ---
67
+ *Analysis completed on {timestamp} | Branch: {branch_name} | Files changed: {files_changed} | Lines: +{lines_added} -{lines_removed}*
@@ -0,0 +1,20 @@
1
+ You are a merge assistant. Combine the following conflict into a single version and explain your reasoning briefly.
2
+
3
+ FULL FILE CONTENT FOR CONTEXT:
4
+ {full_file_content}
5
+
6
+ CONFLICT TO RESOLVE:
7
+ Context before:
8
+ {context_before}
9
+
10
+ <<<<<<< {base_label}
11
+ {base_content}
12
+ =======
13
+ {incoming_content}
14
+ >>>>>>> {incoming_label}
15
+
16
+ Context after:
17
+ {context_after}
18
+ {user_comment}
19
+
20
+ Respond in JSON with keys "merged_code" and "reason".
data/lib/n2b/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # lib/n2b/version.rb
2
2
  module N2B
3
- VERSION = "0.5.0"
3
+ VERSION = "0.7.1"
4
4
  end
data/lib/n2b.rb CHANGED
@@ -12,6 +12,9 @@ require 'n2b/llm/gemini'
12
12
  require 'n2b/errors' # Load custom errors
13
13
  require 'n2b/base'
14
14
  require 'n2b/cli'
15
+ require 'n2b/merge_conflict_parser'
16
+ require 'n2b/merge_cli'
17
+ require 'n2b/template_engine'
15
18
 
16
19
  require 'n2b/irb'
17
20
 
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.5.0
4
+ version: 0.7.1
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-06-05 00:00:00.000000000 Z
11
+ date: 2025-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -52,18 +52,37 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '13.0'
55
- description: A tool to convert natural language instructions to bash commands using
56
- Claude API or OpenAI's GPT. also is q quick helper in the console to provide ruby
57
- code snippets and explanations or debug exceptions.
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ description: 'N2B is a comprehensive AI-powered development toolkit that enhances
70
+ your daily workflow with smart merge conflict resolution, interactive Jira ticket
71
+ analysis, and intelligent code diff analysis. Features include: AI-assisted merge
72
+ conflicts with editor integration, interactive Jira templates with checklists, automatic
73
+ VCS resolution marking, JSON auto-repair, and multi-LLM support (OpenAI, Claude,
74
+ Gemini, OpenRouter, Ollama).'
58
75
  email:
59
76
  - stefan@kaproblem.com
60
77
  executables:
61
78
  - n2b
79
+ - n2b-diff
62
80
  extensions: []
63
81
  extra_rdoc_files: []
64
82
  files:
65
83
  - README.md
66
84
  - bin/n2b
85
+ - bin/n2b-diff
67
86
  - bin/n2b-test-jira
68
87
  - lib/n2b.rb
69
88
  - lib/n2b/base.rb
@@ -77,7 +96,14 @@ files:
77
96
  - lib/n2b/llm/ollama.rb
78
97
  - lib/n2b/llm/open_ai.rb
79
98
  - lib/n2b/llm/open_router.rb
99
+ - lib/n2b/merge_cli.rb
100
+ - lib/n2b/merge_conflict_parser.rb
80
101
  - lib/n2b/model_config.rb
102
+ - lib/n2b/template_engine.rb
103
+ - lib/n2b/templates/diff_json_instruction.txt
104
+ - lib/n2b/templates/diff_system_prompt.txt
105
+ - lib/n2b/templates/jira_comment.txt
106
+ - lib/n2b/templates/merge_conflict_prompt.txt
81
107
  - lib/n2b/version.rb
82
108
  homepage: https://github.com/stefan-kp/n2b
83
109
  licenses:
@@ -86,6 +112,7 @@ metadata:
86
112
  source_code_uri: https://github.com/stefan-kp/n2b
87
113
  changelog_uri: https://github.com/stefan-kp/n2b/blob/main/CHANGELOG.md
88
114
  documentation_uri: https://github.com/stefan-kp/n2b/blob/main/README.md
115
+ rubygems_mfa_required: 'true'
89
116
  post_install_message:
90
117
  rdoc_options: []
91
118
  require_paths:
@@ -101,8 +128,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
101
128
  - !ruby/object:Gem::Version
102
129
  version: '0'
103
130
  requirements: []
104
- rubygems_version: 3.5.3
131
+ rubygems_version: 3.5.22
105
132
  signing_key:
106
133
  specification_version: 4
107
- summary: Convert natural language to bash commands or ruby code and help with debugging.
134
+ summary: AI-powered development toolkit with merge conflict resolution and Jira integration
108
135
  test_files: []