gac 0.16.3__tar.gz → 0.17.1__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.
Potentially problematic release.
This version of gac might be problematic. Click here for more details.
- {gac-0.16.3 → gac-0.17.1}/PKG-INFO +2 -2
- {gac-0.16.3 → gac-0.17.1}/README.md +1 -1
- {gac-0.16.3 → gac-0.17.1}/src/gac/__version__.py +1 -1
- {gac-0.16.3 → gac-0.17.1}/src/gac/cli.py +7 -1
- {gac-0.16.3 → gac-0.17.1}/src/gac/config.py +2 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/constants.py +1 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/main.py +49 -12
- {gac-0.16.3 → gac-0.17.1}/.gitignore +0 -0
- {gac-0.16.3 → gac-0.17.1}/LICENSE +0 -0
- {gac-0.16.3 → gac-0.17.1}/pyproject.toml +0 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/__init__.py +0 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/ai.py +0 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/config_cli.py +0 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/diff_cli.py +0 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/errors.py +0 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/git.py +0 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/init_cli.py +0 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/preprocess.py +0 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/prompt.py +0 -0
- {gac-0.16.3 → gac-0.17.1}/src/gac/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gac
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.1
|
|
4
4
|
Summary: AI-powered Git commit message generator with multi-provider support
|
|
5
5
|
Project-URL: Homepage, https://github.com/cellwebb/gac
|
|
6
6
|
Project-URL: Documentation, https://github.com/cellwebb/gac#readme
|
|
@@ -66,7 +66,7 @@ Description-Content-Type: text/markdown
|
|
|
66
66
|
- **Seamless Git Workflow:** Integrates smoothly into your existing Git routine as a simple drop-in replacement for `git commit`.
|
|
67
67
|
- **Extensive Customization:** Tailor commit messages to your needs with a rich set of flags, including one-liners (`-o`), AI hints (`-h`), commit scope (`-s`), and specific model selection (`-m`).
|
|
68
68
|
- **Streamlined Workflow Commands:** Boost your productivity with convenient options to stage all changes (`-a`), auto-confirm commits (`-y`), and push to your remote repository (`-p`) in a single step.
|
|
69
|
-
- **Reroll
|
|
69
|
+
- **Interactive Reroll with Feedback:** Not satisfied with the generated commit message? Use `r` for a simple regeneration, or `r <feedback>` to provide specific improvement suggestions (e.g., `r make it shorter`, `r focus on the bug fix`).
|
|
70
70
|
- **Token Usage Tracking:** Display token consumption statistics (prompt, completion, and total tokens).
|
|
71
71
|
|
|
72
72
|
## How It Works
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
- **Seamless Git Workflow:** Integrates smoothly into your existing Git routine as a simple drop-in replacement for `git commit`.
|
|
19
19
|
- **Extensive Customization:** Tailor commit messages to your needs with a rich set of flags, including one-liners (`-o`), AI hints (`-h`), commit scope (`-s`), and specific model selection (`-m`).
|
|
20
20
|
- **Streamlined Workflow Commands:** Boost your productivity with convenient options to stage all changes (`-a`), auto-confirm commits (`-y`), and push to your remote repository (`-p`) in a single step.
|
|
21
|
-
- **Reroll
|
|
21
|
+
- **Interactive Reroll with Feedback:** Not satisfied with the generated commit message? Use `r` for a simple regeneration, or `r <feedback>` to provide specific improvement suggestions (e.g., `r make it shorter`, `r focus on the bug fix`).
|
|
22
22
|
- **Token Usage Tracking:** Display token consumption statistics (prompt, completion, and total tokens).
|
|
23
23
|
|
|
24
24
|
## How It Works
|
|
@@ -87,6 +87,12 @@ def cli(
|
|
|
87
87
|
effective_log_level = "ERROR"
|
|
88
88
|
setup_logging(effective_log_level)
|
|
89
89
|
logger.info("Starting gac")
|
|
90
|
+
|
|
91
|
+
# Apply always_include_scope setting if no explicit scope provided
|
|
92
|
+
effective_scope = scope
|
|
93
|
+
if scope is None and config.get("always_include_scope", False):
|
|
94
|
+
effective_scope = "" # Empty string triggers scope inference
|
|
95
|
+
|
|
90
96
|
try:
|
|
91
97
|
main(
|
|
92
98
|
stage_all=add_all,
|
|
@@ -94,7 +100,7 @@ def cli(
|
|
|
94
100
|
hint=hint,
|
|
95
101
|
one_liner=one_liner,
|
|
96
102
|
show_prompt=show_prompt,
|
|
97
|
-
scope=
|
|
103
|
+
scope=effective_scope,
|
|
98
104
|
require_confirmation=not yes,
|
|
99
105
|
push=push,
|
|
100
106
|
quiet=quiet,
|
|
@@ -33,6 +33,8 @@ def load_config() -> dict[str, str | int | float | bool]:
|
|
|
33
33
|
"max_retries": int(os.getenv("GAC_RETRIES", EnvDefaults.MAX_RETRIES)),
|
|
34
34
|
"log_level": os.getenv("GAC_LOG_LEVEL", Logging.DEFAULT_LEVEL),
|
|
35
35
|
"warning_limit_tokens": int(os.getenv("GAC_WARNING_LIMIT_TOKENS", EnvDefaults.WARNING_LIMIT_TOKENS)),
|
|
36
|
+
"always_include_scope": os.getenv("GAC_ALWAYS_INCLUDE_SCOPE", str(EnvDefaults.ALWAYS_INCLUDE_SCOPE)).lower()
|
|
37
|
+
in ("true", "1", "yes", "on"),
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
return config
|
|
@@ -121,7 +121,7 @@ def main(
|
|
|
121
121
|
if warning_limit and prompt_tokens > warning_limit:
|
|
122
122
|
console = Console()
|
|
123
123
|
console.print(
|
|
124
|
-
f"[yellow]⚠️
|
|
124
|
+
f"[yellow]⚠️ WARNING: Prompt contains {prompt_tokens} tokens, which exceeds the warning limit of "
|
|
125
125
|
f"{warning_limit} tokens.[/yellow]"
|
|
126
126
|
)
|
|
127
127
|
if require_confirmation:
|
|
@@ -159,23 +159,58 @@ def main(
|
|
|
159
159
|
)
|
|
160
160
|
|
|
161
161
|
if require_confirmation:
|
|
162
|
-
# Custom prompt that accepts y/n/r
|
|
162
|
+
# Custom prompt that accepts y/n/r or "r <feedback (optional)>"
|
|
163
163
|
while True:
|
|
164
|
-
response = (
|
|
165
|
-
|
|
166
|
-
)
|
|
164
|
+
response = click.prompt(
|
|
165
|
+
"Proceed with commit above? [y/n/r <feedback>]", type=str, show_default=False
|
|
166
|
+
).strip()
|
|
167
167
|
|
|
168
|
-
if response in ["y", "yes"]:
|
|
168
|
+
if response.lower() in ["y", "yes"]:
|
|
169
169
|
break # Exit both loops and proceed with commit
|
|
170
|
-
elif response in ["n", "no"]:
|
|
170
|
+
elif response.lower() in ["n", "no"]:
|
|
171
171
|
console.print("[yellow]Prompt not accepted. Exiting...[/yellow]")
|
|
172
172
|
sys.exit(0)
|
|
173
|
-
elif response
|
|
174
|
-
|
|
173
|
+
elif response.lower() == "r" or response.lower().startswith("r ") or response.lower() == "reroll":
|
|
174
|
+
# Parse the reroll command for optional feedback
|
|
175
|
+
if response.lower() == "r" or response.lower() == "reroll":
|
|
176
|
+
# Simple reroll without feedback
|
|
177
|
+
reroll_feedback = ""
|
|
178
|
+
console.print("[cyan]Regenerating commit message...[/cyan]")
|
|
179
|
+
else:
|
|
180
|
+
# Extract feedback from "r <feedback>"
|
|
181
|
+
reroll_feedback = response[2:].strip() # Remove "r " prefix
|
|
182
|
+
console.print(f"[cyan]Regenerating commit message with feedback: {reroll_feedback}[/cyan]")
|
|
183
|
+
|
|
184
|
+
# Combine hints if reroll feedback provided
|
|
185
|
+
combined_hint = hint
|
|
186
|
+
if reroll_feedback:
|
|
187
|
+
# Create conversational prompt with previous attempt and feedback
|
|
188
|
+
conversational_hint = f"Previous attempt: '{commit_message}'. User feedback: {reroll_feedback}. Please revise accordingly."
|
|
189
|
+
|
|
190
|
+
if hint:
|
|
191
|
+
combined_hint = f"{hint}. {conversational_hint}"
|
|
192
|
+
else:
|
|
193
|
+
combined_hint = conversational_hint
|
|
194
|
+
|
|
195
|
+
# Regenerate prompt with conversational feedback
|
|
196
|
+
reroll_prompt = build_prompt(
|
|
197
|
+
status=status,
|
|
198
|
+
processed_diff=processed_diff,
|
|
199
|
+
diff_stat=diff_stat,
|
|
200
|
+
one_liner=one_liner,
|
|
201
|
+
hint=combined_hint,
|
|
202
|
+
scope=scope,
|
|
203
|
+
)
|
|
204
|
+
else:
|
|
205
|
+
# No hint given, just reroll with same prompt
|
|
206
|
+
reroll_prompt = prompt
|
|
207
|
+
|
|
208
|
+
console.print() # Add blank line for readability
|
|
209
|
+
|
|
175
210
|
# Generate new message
|
|
176
211
|
commit_message = generate_commit_message(
|
|
177
212
|
model=model,
|
|
178
|
-
prompt=
|
|
213
|
+
prompt=reroll_prompt,
|
|
179
214
|
temperature=temperature,
|
|
180
215
|
max_tokens=max_output_tokens,
|
|
181
216
|
max_retries=max_retries,
|
|
@@ -184,10 +219,12 @@ def main(
|
|
|
184
219
|
commit_message = clean_commit_message(commit_message)
|
|
185
220
|
break # Exit inner loop, continue outer loop
|
|
186
221
|
else:
|
|
187
|
-
console.print(
|
|
222
|
+
console.print(
|
|
223
|
+
"[red]Invalid response. Please enter y (yes), n (no), r (reroll), or r <feedback>.[/red]"
|
|
224
|
+
)
|
|
188
225
|
|
|
189
226
|
# If we got here with 'y', break the outer loop
|
|
190
|
-
if response in ["y", "yes"]:
|
|
227
|
+
if response.lower() in ["y", "yes"]:
|
|
191
228
|
break
|
|
192
229
|
else:
|
|
193
230
|
# No confirmation required, exit loop
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|