Initial upload: Local LLM Prompt Manager CLI tool
This commit is contained in:
99
src/commands/commit.py
Normal file
99
src/commands/commit.py
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
"""Git commit message generation command."""
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
from ..git import GitUtils
|
||||||
|
from ..llm import LLMClientFactory
|
||||||
|
|
||||||
|
COMMIT_MESSAGE_PROMPT = """You are a helpful assistant that generates git commit messages.
|
||||||
|
|
||||||
|
Analyze the following git diff and generate a concise, descriptive commit message.
|
||||||
|
|
||||||
|
Diff:
|
||||||
|
{diff}
|
||||||
|
|
||||||
|
Files changed:
|
||||||
|
{files}
|
||||||
|
|
||||||
|
Generate a commit message in the following format:
|
||||||
|
- Maximum 72 characters for the title
|
||||||
|
- Blank line
|
||||||
|
- Detailed description of changes
|
||||||
|
|
||||||
|
Focus on:
|
||||||
|
1. What changed
|
||||||
|
2. Why it changed
|
||||||
|
3. Any breaking changes
|
||||||
|
|
||||||
|
Commit message:"""
|
||||||
|
|
||||||
|
|
||||||
|
@click.command("commit")
|
||||||
|
@click.option("--provider", default=None, help="LLM provider")
|
||||||
|
@click.option("--model", default=None, help="Model name")
|
||||||
|
@click.option("--stream/--no-stream", default=False, help="Stream the response")
|
||||||
|
@click.option("--copy/--no-copy", default=True, help="Copy to clipboard")
|
||||||
|
def generate_commit(
|
||||||
|
provider: Optional[str],
|
||||||
|
model: Optional[str],
|
||||||
|
stream: bool,
|
||||||
|
copy: bool
|
||||||
|
):
|
||||||
|
"""Generate a git commit message from staged changes."""
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.panel import Panel
|
||||||
|
from rich.text import Text
|
||||||
|
|
||||||
|
if not GitUtils.is_git_repo():
|
||||||
|
click.echo("Error: Not in a git repository", err=True)
|
||||||
|
click.echo("Run this command from a directory with a .git folder", err=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
staged_diff = GitUtils.get_staged_diff()
|
||||||
|
staged_files = GitUtils.get_staged_files()
|
||||||
|
|
||||||
|
if not staged_diff:
|
||||||
|
click.echo("No staged changes found", err=True)
|
||||||
|
click.echo("Stage your changes with 'git add' first", err=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not staged_files:
|
||||||
|
click.echo("No files staged", err=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
console = Console()
|
||||||
|
|
||||||
|
click.echo("Generating commit message...")
|
||||||
|
|
||||||
|
prompt = COMMIT_MESSAGE_PROMPT.format(
|
||||||
|
diff=GitUtils.get_diff_summary(staged_diff),
|
||||||
|
files="\n".join(staged_files[:20])
|
||||||
|
)
|
||||||
|
|
||||||
|
client = LLMClientFactory.create(provider=provider)
|
||||||
|
|
||||||
|
if stream:
|
||||||
|
click.echo("\n--- Generated Commit Message ---")
|
||||||
|
response = ""
|
||||||
|
for chunk in client.stream_generate(prompt, model=model):
|
||||||
|
response += chunk
|
||||||
|
console.print(chunk, end="")
|
||||||
|
click.echo()
|
||||||
|
else:
|
||||||
|
response = client.generate(prompt, model=model)
|
||||||
|
|
||||||
|
click.echo("\n--- Generated Commit Message ---")
|
||||||
|
console.print(Panel(Text(response), title="Commit Message"))
|
||||||
|
|
||||||
|
if copy:
|
||||||
|
try:
|
||||||
|
import pyperclip
|
||||||
|
pyperclip.copy(response.strip())
|
||||||
|
click.echo("Copied to clipboard!")
|
||||||
|
except ImportError:
|
||||||
|
click.echo("(Install pyperclip to enable clipboard copy)")
|
||||||
|
|
||||||
|
if click.confirm("\nUse this commit message?"):
|
||||||
|
click.echo(f"\nRun: git commit -m '{response.strip()}'")
|
||||||
Reference in New Issue
Block a user