ai_git 0.0.2 → 0.0.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: 65259ec68cad081e1e9a8de3918eae4b338ae23211c5ccde67ef98e089d2fd29
4
- data.tar.gz: 8de30045b286d41c52cd4bae828ae6236ae513a693c9fcc9dd2ba1fb4c30b197
3
+ metadata.gz: a43b04eaad5bed61c5dbe62df46fb915e83d0481e274c2f440b3be2bd7966660
4
+ data.tar.gz: c74c24c20d94f28a58938ec1f8d0a0d323c15a0522fd6d3596b7f8e51323182d
5
5
  SHA512:
6
- metadata.gz: ff8d20bb06a60b58e4a8fe07b4632541e8a2a8fc00ffd3d8f2b06d22a6800a06e04f59b6f14562104374640a21e44d0621d1621f25fda66da3fcb246144ddcc6
7
- data.tar.gz: 9a32d475d621cfdc506f9c2459c879d9e33de9696e3feac98c755cb86066102cde8a05db2f769b6173cac16e32577940721464224e3a80165de46d28a99f5554
6
+ metadata.gz: 03cbbe8cf09690cc3db34f98bf42e39479672ce464d65de18a6a25d901ea9c8d35c318a0efa4eac06abc3d1f07d1848be24506ca4c6146facff7e9dcb18a1e80
7
+ data.tar.gz: 47a3c30cbb3ed60d128db9d68af240b5404096ffc95643766cb873296f8e3f2ccacc5cbc284be4fdc6d984dd1c310ea2ff01873c5442abb86745e1d34be59c19
data/bin/ai_git CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require_relative "../lib/ai_git"
4
5
 
data/lib/ai_git/git.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "English"
1
4
  module AIGit
2
5
  module Git
3
6
  module_function
@@ -17,7 +20,7 @@ module AIGit
17
20
 
18
21
  def run_command(cmd, args)
19
22
  system("#{cmd} #{args} > /dev/null 2>&1")
20
- raise "Command failed: #{cmd} #{args}" if $?.exitstatus != 0
23
+ raise "Command failed: #{cmd} #{args}" if $CHILD_STATUS.exitstatus != 0
21
24
  end
22
25
  end
23
26
  end
data/lib/ai_git/ollama.rb CHANGED
@@ -1,77 +1,110 @@
1
- require 'net/http'
2
- require 'uri'
3
- require 'json'
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+ require "json"
4
6
 
5
7
  module AIGit
6
8
  module Ollama
7
9
  module_function
8
10
 
9
11
  def escape_json(string)
10
- string.gsub('\\', '\\\\')
11
- .gsub('"', '\"')
12
- .gsub("\n", '\\n')
13
- .gsub("\r", '\\r')
14
- .gsub("\t", '\\t')
12
+ string.gsub("\\", "\\\\")
13
+ .gsub('"', '\"')
14
+ .gsub("\n", '\\n')
15
+ .gsub("\r", '\\r')
16
+ .gsub("\t", '\\t')
15
17
  end
16
18
 
17
- def generate_commit_message(diff)
18
- raise 'No staged changes to generate commit message for' if diff.to_s.strip.empty?
19
+ def generate_commit_message(diff, model_name)
20
+ raise "No staged changes to generate commit message for" if diff.to_s.strip.empty?
19
21
 
20
22
  prompt = <<~PROMPT
21
- You are an expert Git commit message writer. Your only job is to output a commit message nothing else.
23
+ You are an expert Git commit message writer. Output ONLY the commit message no explanations, no markdown, no backticks, no preamble.
24
+
25
+ Here are the changes:
26
+ #{diff}
27
+
28
+ STRICT OUTPUT FORMAT (follow exactly):
29
+
30
+ <short imperative title, max 72 chars>
31
+
32
+ <blank line>
33
+
34
+ ## Summary
35
+ <2–4 bullet points covering the most important changes. Each bullet starts with a verb.>
22
36
 
23
- Here are the changes:
24
- #{diff}
37
+ ## Why
38
+ <1–3 sentences explaining the motivation or context behind the change. Omit if the reason is obvious.>
25
39
 
26
- Rules you MUST follow exactly:
27
- - Output ONLY the commit message. No explanations, no quotes, no markdown, no "Here is the commit message", no backticks.
28
- - Use this exact structure:
29
- 1. First line: Conventional commit type + short imperative title (max 72 chars, ideally < 50)
30
- 2. Second line: blank
31
- 3. Body (optional but recommended): Clear, concise explanation of WHAT changed and WHY.
40
+ RULES:
41
+ - Title line: short, specific, imperative mood (e.g. "Add JWT login with refresh token support"). Avoid vague titles like "Update stuff" or "Fix bug".
42
+ - Summary bullets: describe WHAT changed, not HOW the code looks. Focus on behaviour and impact.
43
+ - Why section: explain the problem being solved or the goal being achieved. Skip if it adds no value.
44
+ - No filler phrases ("this commit", "this PR", "as per discussion").
45
+ - No line should exceed 72 characters.
32
46
 
33
- Examples of good output:
34
- feat: add user authentication flow
47
+ EXAMPLES OF GOOD OUTPUT:
35
48
 
36
- Implemented JWT-based login with refresh tokens. Added protected routes middleware.
49
+ Add JWT-based login with refresh token support
37
50
 
38
- fix: prevent null pointer on missing metadata
51
+ ## Summary
52
+ - Implement login endpoint with access and refresh token issuance
53
+ - Add token refresh route with rotation and expiry validation
54
+ - Protect private routes via middleware that verifies access tokens
55
+ - Store refresh tokens using encrypted HTTP-only cookies
39
56
 
40
- Added nil check in ReportGenerator#process before accessing user preferences.
57
+ ## Why
58
+ Users were being logged out on every page reload. Refresh tokens allow
59
+ sessions to persist securely without requiring re-authentication.
41
60
 
42
- Now generate the commit message:
61
+ ---
62
+
63
+ Prevent nil crash when user preferences are missing
64
+
65
+ ## Summary
66
+ - Add nil guard in ReportGenerator#process before accessing preferences
67
+ - Fall back to system defaults when preferences object is absent
68
+
69
+ ## Why
70
+ Reports were raising NoMethodError in production for users created
71
+ before the preferences feature shipped.
72
+
73
+ ---
74
+
75
+ Now generate the commit message:
43
76
  PROMPT
44
77
 
45
78
  json_body = {
46
- model: 'phi4:14b',
79
+ model: model_name,
47
80
  prompt: prompt,
48
81
  stream: false,
49
82
  # These parameters help a lot with strictness:
50
83
  temperature: 0.3,
51
84
  top_p: 0.9,
52
85
  stop: ["\n\n\n", "```", "Here is", "The commit message"],
53
- num_predict: 400 # Limit output length
86
+ num_predict: 400 # Limit output length
54
87
  }.to_json
55
88
 
56
- uri = URI('http://localhost:11434/api/generate')
89
+ uri = URI("http://localhost:11434/api/generate")
57
90
  request = Net::HTTP::Post.new(uri)
58
- request['Content-Type'] = 'application/json'
91
+ request["Content-Type"] = "application/json"
59
92
  request.body = json_body
60
93
 
61
94
  response = Net::HTTP.start(uri.host, uri.port, read_timeout: 120) do |http|
62
95
  http.request(request)
63
96
  end
64
97
 
65
- raise 'Failed to connect to Ollama. Is it running?' unless response.is_a?(Net::HTTPSuccess)
98
+ raise "Failed to connect to Ollama. Is it running?" unless response.is_a?(Net::HTTPSuccess)
66
99
 
67
100
  data = JSON.parse(response.body)
68
- message = data['response'].to_s.strip
101
+ message = data["response"].to_s.strip
69
102
 
70
103
  # Aggressive cleaning
71
- message = message.gsub(/^(Here is|The commit message is|```|json|markdown)/i, '')
72
- .gsub(/^>\s*/, '')
73
- .gsub(/\\n/, "\n")
74
- .strip
104
+ message = message.gsub(/^(Here is|The commit message is|```|json|markdown)/i, "")
105
+ .gsub(/^>\s*/, "")
106
+ .gsub(/\\n/, "\n")
107
+ .strip
75
108
 
76
109
  # Remove common unwanted prefixes/suffixes
77
110
  lines = message.lines.map(&:strip)
@@ -81,10 +114,10 @@ module AIGit
81
114
 
82
115
  # Ensure it has at least a title
83
116
  if message.lines.count < 1 || message.strip.empty?
84
- message = "chore: update code" # fallback
117
+ message = "chore: update code" # fallback
85
118
  end
86
119
 
87
120
  message
88
- end
121
+ end
89
122
  end
90
123
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AIGit
2
- VERSION = "0.0.2"
4
+ VERSION = "0.0.4"
3
5
  end
data/lib/ai_git.rb CHANGED
@@ -1,33 +1,38 @@
1
- require 'benchmark'
2
- require_relative 'ai_git/version'
3
- require_relative 'ai_git/git'
4
- require_relative 'ai_git/ollama'
1
+ # frozen_string_literal: true
2
+
3
+ require "benchmark"
4
+ require_relative "ai_git/version"
5
+ require_relative "ai_git/git"
6
+ require_relative "ai_git/ollama"
5
7
 
6
8
  module AIGit
7
9
  module_function
8
10
 
9
11
  def run
12
+ model_name = ENV["AI_GIT_MODEL_NAME"] || "phi4:14b"
13
+
10
14
  staged = AIGit::Git.staged_files
11
- abort 'Error: No staged files. Use `git add` first.' if staged.to_s.strip.empty?
15
+ abort "Error: No staged files. Use `git add` first." if staged.to_s.strip.empty?
12
16
 
13
17
  diff = AIGit::Git.diff
14
18
  branch = AIGit::Git.current_branch
15
19
 
20
+ puts "\e[1mModel Name:\e[0m #{model_name}"
16
21
  puts "\e[1mStaged Files:\e[0m #{staged}"
17
22
  puts "\e[1mBranch:\e[0m #{branch}"
18
23
  puts "\e[1mAI Generating Commit Message\e[0m"
19
24
 
20
25
  result = Benchmark.measure do
21
- message = AIGit::Ollama.generate_commit_message(diff)
26
+ message = AIGit::Ollama.generate_commit_message(diff, model_name)
22
27
  message = message.gsub(/\n{2,}/, "\n")
23
28
 
24
29
  puts "\e[1mCommit Message:\e[0m\n\n#{message}\n"
25
30
 
26
31
  escaped_msg = message.gsub(/[\\"`$]/) { |c| "\\#{c}" }
27
- AIGit::Git.run_command('git', "commit -m \"#{escaped_msg}\"")
32
+ AIGit::Git.run_command("git", "commit -m \"#{escaped_msg}\"")
28
33
  puts "\e[1mGit Commited\e[0m"
29
34
 
30
- AIGit::Git.run_command('git', 'push')
35
+ AIGit::Git.run_command("git", "push")
31
36
  puts "\e[1mGit Pushed\e[0m"
32
37
  end
33
38
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ai_git
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaíque Kandy Koga
@@ -9,7 +9,7 @@ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
- description: Generates intelligent commit messages using Ollama LLMs
12
+ description: AI‑powered Git commit + push tool using SLMs
13
13
  executables:
14
14
  - ai_git
15
15
  extensions: []
@@ -40,5 +40,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
40
40
  requirements: []
41
41
  rubygems_version: 4.0.9
42
42
  specification_version: 4
43
- summary: AI-powered git commit and push tool using Ollama
43
+ summary: AIpowered Git commit + push tool using SLMs
44
44
  test_files: []