devcommit 0.1.5.2__tar.gz → 0.1.5.4__tar.gz
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.
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/PKG-INFO +14 -4
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/README.md +13 -3
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/app/ai_providers.py +14 -1
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/app/changelog.py +24 -22
- devcommit-0.1.5.4/devcommit/create_config.py +111 -0
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/utils/git.py +5 -4
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/pyproject.toml +3 -3
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/COPYING +0 -0
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/__init__.py +0 -0
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/__version__.py +0 -0
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/app/__init__.py +0 -0
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/app/gemini_ai.py +0 -0
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/app/prompt.py +0 -0
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/main.py +0 -0
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/utils/__init__.py +0 -0
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/utils/logger.py +0 -0
- {devcommit-0.1.5.2 → devcommit-0.1.5.4}/devcommit/utils/parser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devcommit
|
|
3
|
-
Version: 0.1.5.
|
|
3
|
+
Version: 0.1.5.4
|
|
4
4
|
Summary: AI-powered git commit message generator
|
|
5
5
|
License: GNU GENERAL PUBLIC LICENSE
|
|
6
6
|
Version 3, 29 June 2007
|
|
@@ -803,6 +803,16 @@ A command-line AI tool for autocommits.
|
|
|
803
803
|
|
|
804
804
|
## Usage
|
|
805
805
|
|
|
806
|
+
### Quick Setup
|
|
807
|
+
|
|
808
|
+
Generate a configuration file with default settings:
|
|
809
|
+
|
|
810
|
+
```bash
|
|
811
|
+
create-dcommit
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
This creates a `.dcommit` file in your home directory (or virtual environment config folder) with all available options.
|
|
815
|
+
|
|
806
816
|
After installation, you can start using DevCommit directly in your terminal:
|
|
807
817
|
|
|
808
818
|
```bash
|
|
@@ -1140,8 +1150,8 @@ devcommit --stageAll --changelog --files src/
|
|
|
1140
1150
|
|
|
1141
1151
|
- **With `--stageAll`**: Changelog is generated from unstaged changes **before** staging
|
|
1142
1152
|
- **Without `--stageAll`**: Changelog is generated from the last commit **after** committing
|
|
1143
|
-
- Changelogs are saved as markdown files with datetime-based names (e.g., `2026-01-28_00-55-30.md`)
|
|
1144
|
-
- Default directory: `changelogs/` (configurable via `CHANGELOG_DIR` in `.dcommit`)
|
|
1153
|
+
- Changelogs are saved as markdown files with datetime-based names inside `year/month` folders (e.g., `changelogs/2026/01/2026-01-28_00-55-30.md`)
|
|
1154
|
+
- Default base directory: `changelogs/` (configurable via `CHANGELOG_DIR` in `.dcommit`)
|
|
1145
1155
|
- Uses Keep a Changelog format with AI-generated content
|
|
1146
1156
|
|
|
1147
1157
|
**Example workflow:**
|
|
@@ -1153,7 +1163,7 @@ devcommit --stageAll --changelog --files src/
|
|
|
1153
1163
|
# Stage all changes and generate changelog before committing
|
|
1154
1164
|
devcommit --stageAll --changelog
|
|
1155
1165
|
|
|
1156
|
-
# The changelog file is created in changelogs
|
|
1166
|
+
# The changelog file is created in changelogs/<year>/<month>/ directory
|
|
1157
1167
|
# Then changes are staged and committed
|
|
1158
1168
|
```
|
|
1159
1169
|
|
|
@@ -98,6 +98,16 @@ A command-line AI tool for autocommits.
|
|
|
98
98
|
|
|
99
99
|
## Usage
|
|
100
100
|
|
|
101
|
+
### Quick Setup
|
|
102
|
+
|
|
103
|
+
Generate a configuration file with default settings:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
create-dcommit
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This creates a `.dcommit` file in your home directory (or virtual environment config folder) with all available options.
|
|
110
|
+
|
|
101
111
|
After installation, you can start using DevCommit directly in your terminal:
|
|
102
112
|
|
|
103
113
|
```bash
|
|
@@ -435,8 +445,8 @@ devcommit --stageAll --changelog --files src/
|
|
|
435
445
|
|
|
436
446
|
- **With `--stageAll`**: Changelog is generated from unstaged changes **before** staging
|
|
437
447
|
- **Without `--stageAll`**: Changelog is generated from the last commit **after** committing
|
|
438
|
-
- Changelogs are saved as markdown files with datetime-based names (e.g., `2026-01-28_00-55-30.md`)
|
|
439
|
-
- Default directory: `changelogs/` (configurable via `CHANGELOG_DIR` in `.dcommit`)
|
|
448
|
+
- Changelogs are saved as markdown files with datetime-based names inside `year/month` folders (e.g., `changelogs/2026/01/2026-01-28_00-55-30.md`)
|
|
449
|
+
- Default base directory: `changelogs/` (configurable via `CHANGELOG_DIR` in `.dcommit`)
|
|
440
450
|
- Uses Keep a Changelog format with AI-generated content
|
|
441
451
|
|
|
442
452
|
**Example workflow:**
|
|
@@ -448,7 +458,7 @@ devcommit --stageAll --changelog --files src/
|
|
|
448
458
|
# Stage all changes and generate changelog before committing
|
|
449
459
|
devcommit --stageAll --changelog
|
|
450
460
|
|
|
451
|
-
# The changelog file is created in changelogs
|
|
461
|
+
# The changelog file is created in changelogs/<year>/<month>/ directory
|
|
452
462
|
# Then changes are staged and committed
|
|
453
463
|
```
|
|
454
464
|
|
|
@@ -124,6 +124,8 @@ class OpenAIProvider(AIProvider):
|
|
|
124
124
|
max_tokens=max_tokens,
|
|
125
125
|
temperature=0.7,
|
|
126
126
|
)
|
|
127
|
+
if not response or not response.choices:
|
|
128
|
+
raise ValueError("OpenAI returned empty response (no choices).")
|
|
127
129
|
return response.choices[0].message.content.strip()
|
|
128
130
|
|
|
129
131
|
|
|
@@ -150,6 +152,8 @@ class GroqProvider(AIProvider):
|
|
|
150
152
|
max_tokens=max_tokens,
|
|
151
153
|
temperature=0.7,
|
|
152
154
|
)
|
|
155
|
+
if not response or not response.choices:
|
|
156
|
+
raise ValueError("Groq returned empty response (no choices).")
|
|
153
157
|
return response.choices[0].message.content.strip()
|
|
154
158
|
|
|
155
159
|
|
|
@@ -190,7 +194,14 @@ class OpenRouterProvider(AIProvider):
|
|
|
190
194
|
"X-Title": "DevCommit",
|
|
191
195
|
},
|
|
192
196
|
)
|
|
193
|
-
|
|
197
|
+
if not response or not response.choices:
|
|
198
|
+
raise ValueError("OpenRouter returned empty response (no choices).")
|
|
199
|
+
|
|
200
|
+
content = response.choices[0].message.content
|
|
201
|
+
if not content:
|
|
202
|
+
return ""
|
|
203
|
+
|
|
204
|
+
return content.strip()
|
|
194
205
|
|
|
195
206
|
|
|
196
207
|
class AnthropicProvider(AIProvider):
|
|
@@ -284,6 +295,8 @@ class CustomProvider(AIProvider):
|
|
|
284
295
|
max_tokens=max_tokens,
|
|
285
296
|
temperature=0.7,
|
|
286
297
|
)
|
|
298
|
+
if not response or not response.choices:
|
|
299
|
+
raise ValueError("Custom API returned empty response (no choices).")
|
|
287
300
|
return response.choices[0].message.content.strip()
|
|
288
301
|
|
|
289
302
|
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
import os
|
|
5
5
|
from datetime import datetime
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
from devcommit.app.ai_providers import get_ai_provider
|
|
8
|
+
from devcommit.utils.logger import config
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def generate_changelog_prompt() -> str:
|
|
@@ -41,49 +42,50 @@ Only include sections that have changes. Do not add empty sections."""
|
|
|
41
42
|
|
|
42
43
|
def generate_changelog(diff: str) -> str:
|
|
43
44
|
"""Generate changelog content from git diff using AI.
|
|
44
|
-
|
|
45
|
+
|
|
45
46
|
Args:
|
|
46
47
|
diff: Git diff string
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
Returns:
|
|
49
50
|
Formatted markdown changelog content
|
|
50
51
|
"""
|
|
51
52
|
prompt = generate_changelog_prompt()
|
|
52
|
-
|
|
53
|
-
# Get AI provider from config
|
|
53
|
+
|
|
54
54
|
provider = get_ai_provider(config)
|
|
55
|
-
|
|
56
|
-
# Generate changelog using AI
|
|
55
|
+
|
|
57
56
|
max_tokens = config("MAX_TOKENS", default=8192, cast=int)
|
|
58
|
-
changelog_content = provider.generate_commit_message(
|
|
59
|
-
|
|
57
|
+
changelog_content = provider.generate_commit_message(
|
|
58
|
+
diff, prompt, max_tokens
|
|
59
|
+
)
|
|
60
|
+
|
|
60
61
|
return changelog_content
|
|
61
62
|
|
|
62
63
|
|
|
63
64
|
def save_changelog(content: str, directory: str = None) -> str:
|
|
64
65
|
"""Save changelog content to a file.
|
|
65
|
-
|
|
66
|
+
|
|
66
67
|
Args:
|
|
67
68
|
content: Changelog markdown content
|
|
68
69
|
directory: Directory to save changelog (default from config)
|
|
69
|
-
|
|
70
|
+
|
|
70
71
|
Returns:
|
|
71
72
|
Path to the saved changelog file
|
|
72
73
|
"""
|
|
73
|
-
# Get directory from config if not provided
|
|
74
74
|
if directory is None:
|
|
75
75
|
directory = config("CHANGELOG_DIR", default="changelogs")
|
|
76
|
-
|
|
77
|
-
# Create directory if it doesn't exist
|
|
78
|
-
os.makedirs(directory, exist_ok=True)
|
|
79
|
-
|
|
80
|
-
# Generate filename with current datetime
|
|
76
|
+
|
|
81
77
|
now = datetime.now()
|
|
78
|
+
year_directory = now.strftime("%Y")
|
|
79
|
+
month_directory = now.strftime("%m")
|
|
80
|
+
target_directory = os.path.join(directory, year_directory, month_directory)
|
|
81
|
+
|
|
82
|
+
# Create the year/month directory structure if it doesn't exist
|
|
83
|
+
os.makedirs(target_directory, exist_ok=True)
|
|
84
|
+
|
|
82
85
|
filename = now.strftime("%Y-%m-%d_%H-%M-%S.md")
|
|
83
|
-
filepath = os.path.join(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
with open(filepath, 'w', encoding='utf-8') as f:
|
|
86
|
+
filepath = os.path.join(target_directory, filename)
|
|
87
|
+
|
|
88
|
+
with open(filepath, "w", encoding="utf-8") as f:
|
|
87
89
|
f.write(content)
|
|
88
|
-
|
|
90
|
+
|
|
89
91
|
return filepath
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def create_dcommit():
|
|
5
|
+
dcommit_content = """# DevCommit Configuration File (OPTIONAL)
|
|
6
|
+
# This file is optional - you can use environment variables instead!
|
|
7
|
+
#
|
|
8
|
+
# Copy this file to:
|
|
9
|
+
# - ~/.dcommit (for global config)
|
|
10
|
+
# - $VIRTUAL_ENV/config/.dcommit (for venv-specific config)
|
|
11
|
+
#
|
|
12
|
+
# Or use environment variables:
|
|
13
|
+
# export GEMINI_API_KEY='your-api-key-here'
|
|
14
|
+
# export COMMIT_MODE='directory'
|
|
15
|
+
#
|
|
16
|
+
# Priority: .dcommit file > Environment Variables > Defaults
|
|
17
|
+
|
|
18
|
+
# ════════════════════════════════════════════════════════════════
|
|
19
|
+
# AI Provider Configuration
|
|
20
|
+
# ════════════════════════════════════════════════════════════════
|
|
21
|
+
|
|
22
|
+
# AI Provider (default: gemini)
|
|
23
|
+
# Options: gemini, openai, groq, anthropic, ollama, custom
|
|
24
|
+
AI_PROVIDER = gemini
|
|
25
|
+
|
|
26
|
+
# ─── Gemini (Google) ───
|
|
27
|
+
# Get API key from: https://aistudio.google.com/app/apikey
|
|
28
|
+
GEMINI_API_KEY = your-api-key-here
|
|
29
|
+
GEMINI_MODEL = gemini-2.0-flash-exp
|
|
30
|
+
|
|
31
|
+
# ─── OpenAI ───
|
|
32
|
+
# OPENAI_API_KEY = your-openai-key
|
|
33
|
+
# OPENAI_MODEL = gpt-4o-mini
|
|
34
|
+
|
|
35
|
+
# ─── Groq (Fast & Free) ───
|
|
36
|
+
# Get API key from: https://console.groq.com/
|
|
37
|
+
# GROQ_API_KEY = your-groq-key
|
|
38
|
+
# GROQ_MODEL = llama-3.3-70b-versatile
|
|
39
|
+
|
|
40
|
+
# ─── Anthropic Claude ───
|
|
41
|
+
# ANTHROPIC_API_KEY = your-anthropic-key
|
|
42
|
+
# ANTHROPIC_MODEL = claude-3-haiku-20240307
|
|
43
|
+
|
|
44
|
+
# ─── OpenRouter ───
|
|
45
|
+
# OPENROUTER_API_KEY = your-openrouter-key
|
|
46
|
+
# OPENROUTER_MODEL = meta-llama/llama-3.3-70b-instruct:free
|
|
47
|
+
|
|
48
|
+
# ─── Ollama (Local) ───
|
|
49
|
+
# OLLAMA_BASE_URL = http://localhost:11434
|
|
50
|
+
# OLLAMA_MODEL = llama3
|
|
51
|
+
|
|
52
|
+
# ─── Custom API (OpenAI-compatible) ───
|
|
53
|
+
# CUSTOM_API_URL = http://your-server/v1
|
|
54
|
+
# CUSTOM_API_KEY = your-key
|
|
55
|
+
# CUSTOM_MODEL = your-model-name
|
|
56
|
+
|
|
57
|
+
# ════════════════════════════════════════════════════════════════
|
|
58
|
+
# General Configuration
|
|
59
|
+
# ════════════════════════════════════════════════════════════════
|
|
60
|
+
|
|
61
|
+
# Language/locale for commit messages (default: en-US)
|
|
62
|
+
LOCALE = en
|
|
63
|
+
|
|
64
|
+
# Number of commit message suggestions to generate (default: 1)
|
|
65
|
+
MAX_NO = 1
|
|
66
|
+
|
|
67
|
+
# Type of commit messages (default: general)
|
|
68
|
+
# Options: general, conventional, etc.
|
|
69
|
+
COMMIT_TYPE = conventional
|
|
70
|
+
|
|
71
|
+
# Gemini model to use (default: gemini-1.5-flash)
|
|
72
|
+
MODEL_NAME = gemini-1.5-flash
|
|
73
|
+
|
|
74
|
+
# Commit mode (default: auto)
|
|
75
|
+
# Options:
|
|
76
|
+
# - auto: Prompts when multiple directories are detected
|
|
77
|
+
# - directory: Always use directory-based commits for multiple directories
|
|
78
|
+
# - global: Always create one commit for all changes
|
|
79
|
+
COMMIT_MODE = auto
|
|
80
|
+
|
|
81
|
+
# Files to exclude from diff (default: package-lock.json, pnpm-lock.yaml, yarn.lock, *.lock)
|
|
82
|
+
# Comma-separated list of file patterns
|
|
83
|
+
EXCLUDE_FILES = *.lock, dist/*, build/*, node_modules/*
|
|
84
|
+
|
|
85
|
+
# Directory for changelog files (default: changelogs)
|
|
86
|
+
# Used when --changelog flag is passed
|
|
87
|
+
CHANGELOG_DIR = changelogs
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
if "VIRTUAL_ENV" in os.environ:
|
|
91
|
+
target_directory = os.path.join(
|
|
92
|
+
os.environ.get("VIRTUAL_ENV", ""), "config"
|
|
93
|
+
)
|
|
94
|
+
else:
|
|
95
|
+
target_directory = os.path.expanduser("~/")
|
|
96
|
+
|
|
97
|
+
os.makedirs(target_directory, exist_ok=True)
|
|
98
|
+
dcommit_file = os.path.join(target_directory, ".dcommit")
|
|
99
|
+
|
|
100
|
+
if os.path.exists(dcommit_file):
|
|
101
|
+
print(f"⚠️ Config file already exists at: {dcommit_file}")
|
|
102
|
+
print("❌ Operation cancelled to prevent overwriting.")
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
with open(dcommit_file, "w") as file:
|
|
106
|
+
file.write(dcommit_content.strip())
|
|
107
|
+
print(f"✅ .dcommit file created at: {dcommit_file}")
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
if __name__ == "__main__":
|
|
111
|
+
create_dcommit()
|
|
@@ -358,10 +358,11 @@ def generate_relation_grouping_prompt(files: List[str], diffs: Dict[str, str]) -
|
|
|
358
358
|
" - Example: Adding docker.yaml, kubernetes.yaml, pm2.yaml = ONE GROUP 'add-devops-commands'",
|
|
359
359
|
" - Example: Schema + API + Migration + Tests for same entity = ONE GROUP",
|
|
360
360
|
"",
|
|
361
|
-
"STEP 3:
|
|
362
|
-
" - Separate
|
|
363
|
-
" - A bug fix
|
|
364
|
-
" -
|
|
361
|
+
"STEP 3: SEPARATE BY DISTINCT INTENT",
|
|
362
|
+
" - Separate different KINDS of work (e.g. New Feature vs Bug Fix)",
|
|
363
|
+
" - A bug fix in module A + a new feature in module B = 2 groups",
|
|
364
|
+
" - Documentation updates only = separate group (unless part of a new feature)",
|
|
365
|
+
" - If two changes are unrelated, DO NOT force them together just to reduce groups",
|
|
365
366
|
"",
|
|
366
367
|
"=" * 70,
|
|
367
368
|
"EXAMPLES OF CORRECT GROUPING:",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "devcommit"
|
|
3
|
-
version = "0.1.5.
|
|
3
|
+
version = "0.1.5.4"
|
|
4
4
|
description = "AI-powered git commit message generator"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = {file = "COPYING"}
|
|
@@ -40,11 +40,11 @@ documentation = "https://github.com/Hordunlarmy/DevCommit#readme"
|
|
|
40
40
|
|
|
41
41
|
[project.scripts]
|
|
42
42
|
devcommit = "devcommit.main:main"
|
|
43
|
-
create-dcommit = "
|
|
43
|
+
create-dcommit = "devcommit.create_config:create_dcommit"
|
|
44
44
|
|
|
45
45
|
[tool.poetry]
|
|
46
46
|
name = "devcommit"
|
|
47
|
-
version = "0.1.
|
|
47
|
+
version = "0.1.5.4"
|
|
48
48
|
description = "AI-powered git commit message generator"
|
|
49
49
|
authors = ["Hordunlarmy <Hordunlarmy@gmail.com>"]
|
|
50
50
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|