git-copilot-commit 0.2.1__tar.gz → 0.3.0__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.
- git_copilot_commit-0.3.0/.justfile +59 -0
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/PKG-INFO +2 -2
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/pyproject.toml +1 -1
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/src/git_copilot_commit/cli.py +38 -106
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/src/git_copilot_commit/prompts/commit-message-generator-prompt.md +8 -7
- git_copilot_commit-0.3.0/uv.lock +1174 -0
- git_copilot_commit-0.2.1/.justfile +0 -56
- git_copilot_commit-0.2.1/uv.lock +0 -334
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/.github/workflows/ci.yml +0 -0
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/.gitignore +0 -0
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/.python-version +0 -0
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/LICENSE +0 -0
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/README.md +0 -0
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/src/git_copilot_commit/__init__.py +0 -0
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/src/git_copilot_commit/git.py +0 -0
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/src/git_copilot_commit/py.typed +0 -0
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/src/git_copilot_commit/settings.py +0 -0
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/src/git_copilot_commit/version.py +0 -0
- {git_copilot_commit-0.2.1 → git_copilot_commit-0.3.0}/vhs/demo.vhs +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# List available commands
|
|
2
|
+
[private]
|
|
3
|
+
default:
|
|
4
|
+
@just --list
|
|
5
|
+
|
|
6
|
+
# Pass all arguments directly to git-copilot-commit
|
|
7
|
+
commit *args:
|
|
8
|
+
uv run git-copilot-commit commit {{args}}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Get the next version based on bump type
|
|
12
|
+
next-version type="patch":
|
|
13
|
+
#!/usr/bin/env bash
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
latest_tag=$(gh release list --limit 1 --json tagName --jq '.[0].tagName // "v0.0.0"')
|
|
17
|
+
version=${latest_tag#v}
|
|
18
|
+
IFS='.' read -r major minor patch <<< "$version"
|
|
19
|
+
|
|
20
|
+
case "{{type}}" in
|
|
21
|
+
major)
|
|
22
|
+
major=$((major + 1)); minor=0; patch=0 ;;
|
|
23
|
+
minor)
|
|
24
|
+
minor=$((minor + 1)); patch=0 ;;
|
|
25
|
+
patch)
|
|
26
|
+
patch=$((patch + 1)) ;;
|
|
27
|
+
*)
|
|
28
|
+
echo "Error: Invalid bump type '{{type}}'. Use: major, minor, or patch"; exit 1 ;;
|
|
29
|
+
esac
|
|
30
|
+
|
|
31
|
+
echo "v${major}.${minor}.${patch}"
|
|
32
|
+
|
|
33
|
+
# Bump version and tag it
|
|
34
|
+
bump type="patch":
|
|
35
|
+
#!/usr/bin/env bash
|
|
36
|
+
set -euo pipefail
|
|
37
|
+
|
|
38
|
+
new_version=$(just next-version {{type}})
|
|
39
|
+
echo "New version: $new_version"
|
|
40
|
+
|
|
41
|
+
git commit --allow-empty -m "Bump version to $new_version"
|
|
42
|
+
git tag "$new_version"
|
|
43
|
+
|
|
44
|
+
echo "✓ Created commit and tag for $new_version"
|
|
45
|
+
echo " Run: just release version=$new_version"
|
|
46
|
+
|
|
47
|
+
# Push commit, tag, and create GitHub release
|
|
48
|
+
release version:
|
|
49
|
+
#!/usr/bin/env bash
|
|
50
|
+
set -euo pipefail
|
|
51
|
+
|
|
52
|
+
echo "Pushing commit and tag for $version..."
|
|
53
|
+
git push
|
|
54
|
+
git push origin "$version"
|
|
55
|
+
|
|
56
|
+
echo "Creating GitHub release for $version..."
|
|
57
|
+
gh release create "$version" --title "$version" --generate-notes
|
|
58
|
+
|
|
59
|
+
echo "✓ Release $version created and pushed"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: git-copilot-commit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Automatically generate and commit changes using copilot
|
|
5
5
|
Author-email: Dheepak Krishnamurthy <1813121+kdheepak@users.noreply.github.com>
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Requires-Python: >=3.12
|
|
8
|
+
Requires-Dist: litellm>=1.75.4
|
|
8
9
|
Requires-Dist: platformdirs>=4.0.0
|
|
9
|
-
Requires-Dist: pycopilot>=0.1.7
|
|
10
10
|
Requires-Dist: rich>=14.0.0
|
|
11
11
|
Requires-Dist: typer>=0.16.0
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
@@ -12,8 +12,7 @@ from rich.table import Table
|
|
|
12
12
|
import rich
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
|
|
15
|
-
from
|
|
16
|
-
from pycopilot.auth import Authentication
|
|
15
|
+
from litellm import completion
|
|
17
16
|
from .git import GitRepository, GitError, NotAGitRepositoryError
|
|
18
17
|
from .settings import Settings
|
|
19
18
|
from .version import __version__
|
|
@@ -87,6 +86,29 @@ def load_system_prompt() -> str:
|
|
|
87
86
|
raise typer.Exit(1)
|
|
88
87
|
|
|
89
88
|
|
|
89
|
+
def ask(prompt, model) -> str:
|
|
90
|
+
response = completion(
|
|
91
|
+
model=model,
|
|
92
|
+
messages=[
|
|
93
|
+
{"role": "system", "content": load_system_prompt()},
|
|
94
|
+
{"role": "user", "content": prompt},
|
|
95
|
+
],
|
|
96
|
+
extra_headers={
|
|
97
|
+
"editor-version": "vscode/1.85.1",
|
|
98
|
+
"Copilot-Integration-Id": "vscode-chat",
|
|
99
|
+
},
|
|
100
|
+
)
|
|
101
|
+
text = response.choices[0].message.content
|
|
102
|
+
text = text.strip()
|
|
103
|
+
# Remove triple backticks if they wrap the entire text
|
|
104
|
+
if text.startswith("```") and text.endswith("```"):
|
|
105
|
+
text = text[3:-3].strip()
|
|
106
|
+
# Otherwise remove single backticks if they wrap the entire text
|
|
107
|
+
elif text.startswith("`") and text.endswith("`"):
|
|
108
|
+
text = text[1:-1].strip()
|
|
109
|
+
return text
|
|
110
|
+
|
|
111
|
+
|
|
90
112
|
def generate_commit_message(
|
|
91
113
|
repo: GitRepository, model: str | None = None, context: str = ""
|
|
92
114
|
) -> str:
|
|
@@ -99,9 +121,6 @@ def generate_commit_message(
|
|
|
99
121
|
console.print("[red]No staged changes to commit.[/red]")
|
|
100
122
|
raise typer.Exit()
|
|
101
123
|
|
|
102
|
-
system_prompt = load_system_prompt()
|
|
103
|
-
client = Copilot(system_prompt=system_prompt)
|
|
104
|
-
|
|
105
124
|
prompt_parts = [
|
|
106
125
|
"`git status`:\n",
|
|
107
126
|
f"```\n{status.get_porcelain_output()}\n```",
|
|
@@ -116,11 +135,19 @@ def generate_commit_message(
|
|
|
116
135
|
|
|
117
136
|
prompt = "\n".join(prompt_parts)
|
|
118
137
|
|
|
138
|
+
if model is None:
|
|
139
|
+
model = "github_copilot/gpt-4"
|
|
140
|
+
|
|
141
|
+
if not model.startswith("github_copilot/"):
|
|
142
|
+
model = f"github_copilot/{model}"
|
|
143
|
+
|
|
119
144
|
try:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
145
|
+
return ask(prompt, model=model)
|
|
146
|
+
except Exception as _:
|
|
147
|
+
console.print(
|
|
148
|
+
"Prompt failed, falling back to simpler commit message generation."
|
|
149
|
+
)
|
|
150
|
+
|
|
124
151
|
fallback_prompt_parts = [
|
|
125
152
|
"`git status`:\n",
|
|
126
153
|
f"```\n{status.get_porcelain_output()}\n```",
|
|
@@ -137,13 +164,7 @@ def generate_commit_message(
|
|
|
137
164
|
|
|
138
165
|
fallback_prompt = "\n".join(fallback_prompt_parts)
|
|
139
166
|
|
|
140
|
-
|
|
141
|
-
response = (
|
|
142
|
-
client.ask(fallback_prompt, model=model)
|
|
143
|
-
if model
|
|
144
|
-
else client.ask(fallback_prompt)
|
|
145
|
-
)
|
|
146
|
-
return response.content
|
|
167
|
+
return ask(fallback_prompt, model=model)
|
|
147
168
|
|
|
148
169
|
|
|
149
170
|
@app.command()
|
|
@@ -221,9 +242,7 @@ def commit(
|
|
|
221
242
|
):
|
|
222
243
|
commit_message = generate_commit_message(repo, model, context=context)
|
|
223
244
|
|
|
224
|
-
console.print(
|
|
225
|
-
"[yellow]Generated commit message based on [bold]`git diff --staged`[/] ...[/yellow]"
|
|
226
|
-
)
|
|
245
|
+
console.print("[yellow]Generated commit message.[/yellow]")
|
|
227
246
|
|
|
228
247
|
# Display commit message
|
|
229
248
|
console.print(
|
|
@@ -275,47 +294,6 @@ def commit(
|
|
|
275
294
|
console.print(f"[green]✓ Successfully committed: {commit_sha[:8]}[/green]")
|
|
276
295
|
|
|
277
296
|
|
|
278
|
-
@app.command()
|
|
279
|
-
def authenticate():
|
|
280
|
-
"""Autheticate with GitHub Copilot."""
|
|
281
|
-
Authentication().auth()
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
@app.command()
|
|
285
|
-
def models():
|
|
286
|
-
"""List models available for chat in a table."""
|
|
287
|
-
models = Copilot().models
|
|
288
|
-
|
|
289
|
-
console = Console()
|
|
290
|
-
table = Table(title="Available Models")
|
|
291
|
-
|
|
292
|
-
table.add_column("ID", style="cyan", no_wrap=True)
|
|
293
|
-
table.add_column("Name", style="magenta")
|
|
294
|
-
table.add_column("Vendor", style="green")
|
|
295
|
-
table.add_column("Version", style="yellow")
|
|
296
|
-
table.add_column("Family", style="white")
|
|
297
|
-
table.add_column("Max Tokens", style="white")
|
|
298
|
-
table.add_column("Streaming", style="white")
|
|
299
|
-
|
|
300
|
-
for model in models:
|
|
301
|
-
capabilities = model.get("capabilities", {})
|
|
302
|
-
family = capabilities.get("family", "N/A")
|
|
303
|
-
max_tokens = capabilities.get("limits", {}).get("max_output_tokens", "N/A")
|
|
304
|
-
streaming = capabilities.get("supports", {}).get("streaming", False)
|
|
305
|
-
|
|
306
|
-
table.add_row(
|
|
307
|
-
model.get("id", "N/A"),
|
|
308
|
-
model.get("name", "N/A"),
|
|
309
|
-
model.get("vendor", "N/A"),
|
|
310
|
-
model.get("version", "N/A"),
|
|
311
|
-
family,
|
|
312
|
-
str(max_tokens),
|
|
313
|
-
str(streaming),
|
|
314
|
-
)
|
|
315
|
-
|
|
316
|
-
console.print(table)
|
|
317
|
-
|
|
318
|
-
|
|
319
297
|
@app.command()
|
|
320
298
|
def config(
|
|
321
299
|
set_default_model: str | None = typer.Option(
|
|
@@ -347,51 +325,5 @@ def config(
|
|
|
347
325
|
console.print(f"Config file: [dim]{settings.config_file}[/dim]")
|
|
348
326
|
|
|
349
327
|
|
|
350
|
-
@app.command()
|
|
351
|
-
def echo(
|
|
352
|
-
model: str | None = typer.Option(
|
|
353
|
-
None, "--model", "-m", help="Model to use for generating commit message"
|
|
354
|
-
),
|
|
355
|
-
):
|
|
356
|
-
"""
|
|
357
|
-
Generate commit message from stdin input (useful for pipes).
|
|
358
|
-
"""
|
|
359
|
-
# Read from stdin
|
|
360
|
-
input_text = sys.stdin.read()
|
|
361
|
-
|
|
362
|
-
if not input_text.strip():
|
|
363
|
-
console.print("[red]Error: No input provided via stdin[/red]")
|
|
364
|
-
raise typer.Exit(1)
|
|
365
|
-
|
|
366
|
-
# Load settings and use default model if none provided
|
|
367
|
-
settings = Settings()
|
|
368
|
-
if model is None:
|
|
369
|
-
model = settings.default_model
|
|
370
|
-
|
|
371
|
-
# Load system prompt and create client
|
|
372
|
-
system_prompt = load_system_prompt()
|
|
373
|
-
client = Copilot(system_prompt=system_prompt)
|
|
374
|
-
|
|
375
|
-
# Generate commit message from the input
|
|
376
|
-
prompt = f"""
|
|
377
|
-
`git diff --staged`:
|
|
378
|
-
|
|
379
|
-
```
|
|
380
|
-
{input_text.strip()}
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
Generate a conventional commit message based on the input above:"""
|
|
384
|
-
|
|
385
|
-
try:
|
|
386
|
-
response = client.ask(prompt, model=model) if model else client.ask(prompt)
|
|
387
|
-
# Print the commit message directly to stdout (no rich formatting for pipes)
|
|
388
|
-
import builtins
|
|
389
|
-
|
|
390
|
-
builtins.print(response.content)
|
|
391
|
-
except CopilotAPIError as e:
|
|
392
|
-
console.print(f"[red]Error generating commit message: {e}[/red]")
|
|
393
|
-
raise typer.Exit(1)
|
|
394
|
-
|
|
395
|
-
|
|
396
328
|
if __name__ == "__main__":
|
|
397
329
|
app()
|
|
@@ -7,7 +7,7 @@ You are a Git commit message assistant trained to write a single clear, structur
|
|
|
7
7
|
|
|
8
8
|
Your task is to generate a **single-line commit message** in the [Conventional Commits](https://www.conventionalcommits.org/) format based on both inputs. If no context is provided, rely **only** on the diff.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Output Format
|
|
11
11
|
|
|
12
12
|
```
|
|
13
13
|
<type>(<optional scope>): <description>
|
|
@@ -17,7 +17,7 @@ Your task is to generate a **single-line commit message** in the [Conventional C
|
|
|
17
17
|
- Do not wrap the message in backticks or code blocks.
|
|
18
18
|
- Keep the title line ≤72 characters.
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## Valid Types
|
|
21
21
|
|
|
22
22
|
- `feat`: New feature
|
|
23
23
|
- `fix`: Bug fix
|
|
@@ -29,34 +29,35 @@ Your task is to generate a **single-line commit message** in the [Conventional C
|
|
|
29
29
|
- `chore`: Maintenance tasks (e.g., CI/CD, dependencies)
|
|
30
30
|
- `revert`: Revert of a previous commit
|
|
31
31
|
|
|
32
|
-
##
|
|
32
|
+
## Scope (Optional)
|
|
33
33
|
|
|
34
34
|
- Lowercase, single word or hyphenated phrase
|
|
35
35
|
- Represents the affected area, module, or file
|
|
36
36
|
- Use broad area if multiple related files are affected
|
|
37
37
|
|
|
38
|
-
##
|
|
38
|
+
## Subject Line
|
|
39
39
|
|
|
40
40
|
- Use imperative mood ("remove" not "removed")
|
|
41
41
|
- Focus on **what** changed, not why or how
|
|
42
42
|
- Be concise and specific
|
|
43
43
|
- Use abbreviations (e.g., "config" not "configuration")
|
|
44
44
|
|
|
45
|
-
##
|
|
45
|
+
## Using User-Provided Context
|
|
46
46
|
|
|
47
47
|
- If additional context is provided by the user, you may **incorporate it** to clarify purpose (e.g., "remove duplicate entry").
|
|
48
48
|
- If no such context is provided, **do not speculate or infer**.
|
|
49
49
|
- Only use terms like "unused", "duplicate", or "deprecated" when explicitly stated by the user or clearly shown in the diff.
|
|
50
50
|
|
|
51
|
-
##
|
|
51
|
+
## Do Not
|
|
52
52
|
|
|
53
53
|
- Do not use vague phrases ("made changes", "updated code")
|
|
54
54
|
- Do not use past tense ("added", "removed")
|
|
55
55
|
- Do not explain implementation or reasoning ("to fix bug", "because of issue")
|
|
56
56
|
- Do not guess purpose based on intuition or incomplete file context
|
|
57
|
+
- Do not wrap the response in single backticks.
|
|
57
58
|
|
|
58
59
|
---
|
|
59
60
|
|
|
60
61
|
Given a Git diff, a list of modified files, or a short description of changes, generate a single, short, clear and structured Conventional Commit message following the above rules. If multiple changes are detected, prioritize the most important changes in a single commit message. Do not add any body or footer. You can only give one reply for each conversation.
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
Return the commit message as the output without any additional text, explanations, or formatting markers.
|