git-commit-msg-ai 2.1.2__py3-none-any.whl → 2.3.0__py3-none-any.whl
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_commit_msg_ai/ai_client.py +28 -4
- git_commit_msg_ai/cli.py +35 -16
- git_commit_msg_ai/config.py +79 -17
- git_commit_msg_ai/git_ops.py +28 -7
- {git_commit_msg_ai-2.1.2.dist-info → git_commit_msg_ai-2.3.0.dist-info}/METADATA +14 -7
- git_commit_msg_ai-2.3.0.dist-info/RECORD +13 -0
- git_commit_msg_ai-2.1.2.dist-info/RECORD +0 -13
- {git_commit_msg_ai-2.1.2.dist-info → git_commit_msg_ai-2.3.0.dist-info}/WHEEL +0 -0
- {git_commit_msg_ai-2.1.2.dist-info → git_commit_msg_ai-2.3.0.dist-info}/entry_points.txt +0 -0
- {git_commit_msg_ai-2.1.2.dist-info → git_commit_msg_ai-2.3.0.dist-info}/licenses/LICENSE +0 -0
- {git_commit_msg_ai-2.1.2.dist-info → git_commit_msg_ai-2.3.0.dist-info}/top_level.txt +0 -0
git_commit_msg_ai/ai_client.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import textwrap
|
|
3
|
-
from typing import Final
|
|
3
|
+
from typing import Final, cast
|
|
4
4
|
|
|
5
5
|
import anthropic
|
|
6
|
-
from anthropic.types import CacheControlEphemeralParam, TextBlockParam
|
|
6
|
+
from anthropic.types import CacheControlEphemeralParam, MessageParam, TextBlockParam
|
|
7
7
|
|
|
8
8
|
from git_commit_msg_ai.exceptions import AIError
|
|
9
9
|
|
|
@@ -27,16 +27,40 @@ def _build_system_prompt(types: tuple[str, ...]) -> list[TextBlockParam]:
|
|
|
27
27
|
return [TextBlockParam(type="text", text=text, cache_control=CacheControlEphemeralParam(type="ephemeral"))]
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
def
|
|
30
|
+
def _build_user_message(diff: str, recent_commits: list[str] | None, branch_name: str | None) -> str:
|
|
31
|
+
parts: list[str] = []
|
|
32
|
+
if branch_name:
|
|
33
|
+
parts.append(f"Branch: {branch_name}")
|
|
34
|
+
if recent_commits:
|
|
35
|
+
commit_lines = ["Recent commits (most recent first):"] + [f"- {commit}" for commit in recent_commits]
|
|
36
|
+
parts.append("\n".join(commit_lines))
|
|
37
|
+
if parts:
|
|
38
|
+
parts.append("\n".join(["Staged diff:", diff]))
|
|
39
|
+
return "\n\n".join(parts)
|
|
40
|
+
return diff
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def generate_commit_message(
|
|
44
|
+
diff: str,
|
|
45
|
+
types: tuple[str, ...],
|
|
46
|
+
*,
|
|
47
|
+
recent_commits: list[str] | None = None,
|
|
48
|
+
branch_name: str | None = None,
|
|
49
|
+
conversation_history: list[dict[str, str]] | None = None,
|
|
50
|
+
) -> str:
|
|
31
51
|
try:
|
|
32
52
|
anthropic_client = anthropic.Anthropic()
|
|
33
53
|
|
|
54
|
+
user_message = _build_user_message(diff, recent_commits, branch_name)
|
|
55
|
+
messages: list[MessageParam] = [{"role": "user", "content": user_message}]
|
|
56
|
+
if conversation_history:
|
|
57
|
+
messages.extend(cast(list[MessageParam], conversation_history))
|
|
34
58
|
logger.debug(f"Calling Anthropic API: model={MODEL} max_tokens={MAX_TOKENS}")
|
|
35
59
|
anthropic_api_response = anthropic_client.messages.create(
|
|
36
60
|
model=MODEL,
|
|
37
61
|
max_tokens=MAX_TOKENS,
|
|
38
62
|
system=_build_system_prompt(types),
|
|
39
|
-
messages=
|
|
63
|
+
messages=messages,
|
|
40
64
|
)
|
|
41
65
|
except anthropic.AuthenticationError:
|
|
42
66
|
raise AIError("Anthropic API key is missing or invalid. Set the ANTHROPIC_API_KEY environment variable.")
|
git_commit_msg_ai/cli.py
CHANGED
|
@@ -24,27 +24,46 @@ def main() -> None:
|
|
|
24
24
|
|
|
25
25
|
logging.basicConfig(level=effective_log_level, format=LOG_FORMAT, stream=sys.stderr)
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
all_types = config.get_all_types(optional_types)
|
|
27
|
+
app_config = config.load_config()
|
|
29
28
|
|
|
30
29
|
try:
|
|
31
30
|
diff = git_ops.get_staged_diff()
|
|
32
|
-
|
|
31
|
+
recent_commits = git_ops.get_recent_commit_messages(app_config.context_commits)
|
|
32
|
+
branch_name = git_ops.get_branch_name()
|
|
33
|
+
commit_message = ai_client.generate_commit_message(diff, app_config.types, recent_commits=recent_commits, branch_name=branch_name)
|
|
33
34
|
print(commit_message)
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
36
|
+
conversation_history: list[dict[str, str]] = [{"role": "assistant", "content": commit_message}]
|
|
37
|
+
|
|
38
|
+
while True:
|
|
39
|
+
print()
|
|
40
|
+
user_selection = input("[a]ccept / [e]dit / [r]eject / [f]eedback: ").strip().lower()
|
|
41
|
+
|
|
42
|
+
if user_selection == "a":
|
|
43
|
+
git_ops.commit(commit_message)
|
|
44
|
+
break
|
|
45
|
+
elif user_selection == "e":
|
|
46
|
+
updated_commit_message = editor.open_in_editor(commit_message)
|
|
47
|
+
git_ops.commit(updated_commit_message)
|
|
48
|
+
break
|
|
49
|
+
elif user_selection == "r":
|
|
50
|
+
print("User rejected the generated commit message. No commit made.")
|
|
51
|
+
break
|
|
52
|
+
elif user_selection == "f":
|
|
53
|
+
feedback = input("Feedback: ").strip()
|
|
54
|
+
conversation_history.append({"role": "user", "content": feedback})
|
|
55
|
+
commit_message = ai_client.generate_commit_message(
|
|
56
|
+
diff,
|
|
57
|
+
app_config.types,
|
|
58
|
+
recent_commits=recent_commits,
|
|
59
|
+
branch_name=branch_name,
|
|
60
|
+
conversation_history=list(conversation_history),
|
|
61
|
+
)
|
|
62
|
+
print(commit_message)
|
|
63
|
+
conversation_history.append({"role": "assistant", "content": commit_message})
|
|
64
|
+
else:
|
|
65
|
+
print("Invalid selection.")
|
|
66
|
+
sys.exit(1)
|
|
48
67
|
except GitCommitAIError as error:
|
|
49
68
|
logger.error(str(error))
|
|
50
69
|
print(f"Error: {error}", file=sys.stderr)
|
git_commit_msg_ai/config.py
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import tomllib
|
|
3
|
+
from dataclasses import dataclass
|
|
3
4
|
from pathlib import Path
|
|
4
|
-
from typing import Final
|
|
5
|
+
from typing import Any, Final, cast
|
|
5
6
|
|
|
6
7
|
logger = logging.getLogger(__name__)
|
|
7
8
|
|
|
8
9
|
MANDATORY_TYPES: Final[tuple[str, ...]] = ("feat", "fix", "revert")
|
|
9
10
|
DEFAULT_OPTIONAL_TYPES: Final[tuple[str, ...]] = ("build", "ci", "docs", "perf", "refactor", "style", "test")
|
|
11
|
+
CONTEXT_COMMITS_DEFAULT: Final[int] = 5
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class AppConfig:
|
|
16
|
+
types: tuple[str, ...]
|
|
17
|
+
context_commits: int
|
|
10
18
|
|
|
11
19
|
|
|
12
20
|
def _find_pyproject_toml() -> Path | None:
|
|
@@ -25,10 +33,20 @@ def _parse_types_list(types_value: object, source: str) -> tuple[str, ...] | Non
|
|
|
25
33
|
logger.warning(f"'types' in {source} must be a TOML array, skipping")
|
|
26
34
|
return None
|
|
27
35
|
|
|
28
|
-
|
|
36
|
+
entries = cast(list[object], types_value)
|
|
37
|
+
return tuple(entry.strip().lower() for entry in entries if isinstance(entry, str) and entry.strip())
|
|
38
|
+
|
|
29
39
|
|
|
40
|
+
def _parse_context_commits(value: object, source: str) -> int | None:
|
|
41
|
+
if value is None:
|
|
42
|
+
return None
|
|
43
|
+
if isinstance(value, bool) or not isinstance(value, int):
|
|
44
|
+
logger.warning(f"'context_commits' in {source} must be an integer, skipping")
|
|
45
|
+
return None
|
|
46
|
+
return max(0, value)
|
|
30
47
|
|
|
31
|
-
|
|
48
|
+
|
|
49
|
+
def _read_pkg_section_from_pyproject_toml(path: Path) -> dict[str, object] | None:
|
|
32
50
|
try:
|
|
33
51
|
with open(path, "rb") as toml_file:
|
|
34
52
|
data = tomllib.load(toml_file)
|
|
@@ -40,41 +58,85 @@ def _load_from_pyproject_toml(path: Path) -> tuple[str, ...] | None:
|
|
|
40
58
|
if not isinstance(tool_section, dict):
|
|
41
59
|
return None
|
|
42
60
|
|
|
43
|
-
pkg_section = tool_section.get("git-commit-msg-ai")
|
|
44
|
-
if
|
|
45
|
-
return None
|
|
46
|
-
|
|
47
|
-
return _parse_types_list(pkg_section.get("types"), f"[tool.git-commit-msg-ai] in {path}")
|
|
61
|
+
pkg_section = cast(dict[str, object], tool_section).get("git-commit-msg-ai")
|
|
62
|
+
return cast(dict[str, object], pkg_section) if isinstance(pkg_section, dict) else None
|
|
48
63
|
|
|
49
64
|
|
|
50
|
-
def
|
|
51
|
-
|
|
52
|
-
if not
|
|
65
|
+
def _read_global_config_data() -> dict[str, Any] | None:
|
|
66
|
+
path = Path.home() / ".git-commit-msg-ai.toml"
|
|
67
|
+
if not path.is_file():
|
|
53
68
|
return None
|
|
54
69
|
|
|
55
70
|
try:
|
|
56
|
-
with open(
|
|
57
|
-
|
|
71
|
+
with open(path, "rb") as toml_file:
|
|
72
|
+
return tomllib.load(toml_file)
|
|
58
73
|
except tomllib.TOMLDecodeError:
|
|
59
|
-
logger.warning(f"Could not parse {
|
|
74
|
+
logger.warning(f"Could not parse {path}, using defaults")
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _load_types_from_pyproject_toml(path: Path) -> tuple[str, ...] | None:
|
|
79
|
+
section = _read_pkg_section_from_pyproject_toml(path)
|
|
80
|
+
if section is None:
|
|
60
81
|
return None
|
|
82
|
+
return _parse_types_list(section.get("types"), f"[tool.git-commit-msg-ai] in {path}")
|
|
61
83
|
|
|
62
|
-
|
|
84
|
+
|
|
85
|
+
def _load_types_from_global_config() -> tuple[str, ...] | None:
|
|
86
|
+
data = _read_global_config_data()
|
|
87
|
+
if data is None:
|
|
88
|
+
return None
|
|
89
|
+
return _parse_types_list(data.get("types"), str(Path.home() / ".git-commit-msg-ai.toml"))
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _load_context_commits_from_pyproject_toml(path: Path) -> int | None:
|
|
93
|
+
section = _read_pkg_section_from_pyproject_toml(path)
|
|
94
|
+
if section is None:
|
|
95
|
+
return None
|
|
96
|
+
return _parse_context_commits(section.get("context_commits"), f"[tool.git-commit-msg-ai] in {path}")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _load_context_commits_from_global_config() -> int | None:
|
|
100
|
+
data = _read_global_config_data()
|
|
101
|
+
if data is None:
|
|
102
|
+
return None
|
|
103
|
+
return _parse_context_commits(data.get("context_commits"), str(Path.home() / ".git-commit-msg-ai.toml"))
|
|
63
104
|
|
|
64
105
|
|
|
65
106
|
def load_optional_types() -> tuple[str, ...]:
|
|
66
107
|
pyproject_path = _find_pyproject_toml()
|
|
67
108
|
if pyproject_path is not None:
|
|
68
|
-
result =
|
|
109
|
+
result = _load_types_from_pyproject_toml(pyproject_path)
|
|
69
110
|
if result is not None:
|
|
70
111
|
return result
|
|
71
112
|
|
|
72
|
-
result =
|
|
113
|
+
result = _load_types_from_global_config()
|
|
73
114
|
if result is not None:
|
|
74
115
|
return result
|
|
75
116
|
|
|
76
117
|
return DEFAULT_OPTIONAL_TYPES
|
|
77
118
|
|
|
78
119
|
|
|
120
|
+
def load_context_commits() -> int:
|
|
121
|
+
pyproject_path = _find_pyproject_toml()
|
|
122
|
+
if pyproject_path is not None:
|
|
123
|
+
result = _load_context_commits_from_pyproject_toml(pyproject_path)
|
|
124
|
+
if result is not None:
|
|
125
|
+
return result
|
|
126
|
+
|
|
127
|
+
result = _load_context_commits_from_global_config()
|
|
128
|
+
if result is not None:
|
|
129
|
+
return result
|
|
130
|
+
|
|
131
|
+
return CONTEXT_COMMITS_DEFAULT
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def load_config() -> AppConfig:
|
|
135
|
+
return AppConfig(
|
|
136
|
+
types=get_all_types(load_optional_types()),
|
|
137
|
+
context_commits=load_context_commits(),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
79
141
|
def get_all_types(optional_types: tuple[str, ...]) -> tuple[str, ...]:
|
|
80
142
|
return tuple(dict.fromkeys(MANDATORY_TYPES + optional_types))
|
git_commit_msg_ai/git_ops.py
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import subprocess
|
|
3
|
-
from typing import Final
|
|
4
3
|
|
|
5
4
|
from git_commit_msg_ai.exceptions import GitError
|
|
6
5
|
|
|
7
|
-
GIT_COMMAND: Final[str] = "git"
|
|
8
|
-
|
|
9
6
|
logger = logging.getLogger(__name__)
|
|
10
7
|
|
|
11
8
|
|
|
12
9
|
def get_staged_diff() -> str:
|
|
13
10
|
try:
|
|
14
|
-
logger.debug(
|
|
15
|
-
raw_diff_bytes = subprocess.check_output([
|
|
11
|
+
logger.debug("Running: git diff --cached")
|
|
12
|
+
raw_diff_bytes = subprocess.check_output(["git", "diff", "--cached"])
|
|
16
13
|
staged_diff = raw_diff_bytes.decode("utf-8")
|
|
17
14
|
except FileNotFoundError:
|
|
18
15
|
raise GitError("git is not installed or not on PATH.")
|
|
@@ -29,10 +26,34 @@ def get_staged_diff() -> str:
|
|
|
29
26
|
return staged_diff
|
|
30
27
|
|
|
31
28
|
|
|
29
|
+
def get_recent_commit_messages(n: int) -> list[str]:
|
|
30
|
+
if n <= 0:
|
|
31
|
+
return []
|
|
32
|
+
try:
|
|
33
|
+
logger.debug(f"Running: git log --format=%s -n {n}")
|
|
34
|
+
raw_git_log_bytes = subprocess.check_output(["git", "log", "--format=%s", f"-n{n}"])
|
|
35
|
+
commit_message_lines = raw_git_log_bytes.decode("utf-8").splitlines()
|
|
36
|
+
return [commit_message for commit_message in commit_message_lines if commit_message.strip()]
|
|
37
|
+
except Exception:
|
|
38
|
+
logger.debug("Could not retrieve recent commit messages; proceeding without context")
|
|
39
|
+
return []
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_branch_name() -> str | None:
|
|
43
|
+
try:
|
|
44
|
+
logger.debug("Running: git rev-parse --abbrev-ref HEAD")
|
|
45
|
+
raw_branch_name_bytes = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"])
|
|
46
|
+
branch_name = raw_branch_name_bytes.decode("utf-8").strip()
|
|
47
|
+
return branch_name if branch_name != "HEAD" else None
|
|
48
|
+
except Exception:
|
|
49
|
+
logger.debug("Could not retrieve branch name; proceeding without context")
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
|
|
32
53
|
def commit(message: str) -> None:
|
|
33
54
|
try:
|
|
34
|
-
logger.debug(
|
|
35
|
-
subprocess.run([
|
|
55
|
+
logger.debug("Running: git commit -m <message>")
|
|
56
|
+
subprocess.run(["git", "commit", "-m", message], check=True)
|
|
36
57
|
except FileNotFoundError:
|
|
37
58
|
raise GitError("git is not installed or not on PATH.")
|
|
38
59
|
except subprocess.CalledProcessError:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: git-commit-msg-ai
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: AI-powered git commit message generator following Conventional Commits
|
|
5
5
|
License: MIT License
|
|
6
6
|
|
|
@@ -118,12 +118,15 @@ The tool will:
|
|
|
118
118
|
3. Print the message and prompt you to choose:
|
|
119
119
|
|
|
120
120
|
```
|
|
121
|
-
[a]ccept / [e]dit / [r]eject:
|
|
121
|
+
[a]ccept / [e]dit / [r]eject / [f]eedback:
|
|
122
122
|
```
|
|
123
123
|
|
|
124
124
|
- **a** - commits immediately with the generated message
|
|
125
125
|
- **e** - opens the message in your `$EDITOR` (defaults to `notepad` on Windows, `vi` on Linux/macOS), lets you modify it, then commits
|
|
126
126
|
- **r** - exits without committing
|
|
127
|
+
- **f** - prompts you for natural-language feedback, regenerates the message incorporating that feedback, and loops back so you can keep refining until satisfied
|
|
128
|
+
|
|
129
|
+
The tool automatically reads the current branch name and recent commit history and includes them in the request to the AI. This helps the AI match the commit style already established in the project. No configuration is required to enable this; see [Configuration](#configuration) to control how many recent commits are included.
|
|
127
130
|
|
|
128
131
|
## Commit message format
|
|
129
132
|
|
|
@@ -156,11 +159,11 @@ The set of optional commit types the AI may use can be customised through a conf
|
|
|
156
159
|
|
|
157
160
|
### Config file locations and precedence
|
|
158
161
|
|
|
159
|
-
The tool checks the following locations in order, using the first one that defines a
|
|
162
|
+
The tool checks the following locations in order, using the first one that defines a given setting:
|
|
160
163
|
|
|
161
164
|
1. **Project-level** — `pyproject.toml` walked up from the current working directory, under `[tool.git-commit-msg-ai]`
|
|
162
165
|
2. **User-level** — `~/.git-commit-msg-ai.toml` in your home directory
|
|
163
|
-
3. **Built-in defaults** — used when neither config file is present or neither defines
|
|
166
|
+
3. **Built-in defaults** — used when neither config file is present or neither defines the setting
|
|
164
167
|
|
|
165
168
|
### Config file formats
|
|
166
169
|
|
|
@@ -169,16 +172,20 @@ Project-level (`pyproject.toml`):
|
|
|
169
172
|
```toml
|
|
170
173
|
[tool.git-commit-msg-ai]
|
|
171
174
|
types = ["build", "ci", "docs", "perf", "refactor", "style", "test"]
|
|
175
|
+
context_commits = 10 # include last 10 commits for context (default: 5)
|
|
172
176
|
```
|
|
173
177
|
|
|
174
178
|
User-level (`~/.git-commit-msg-ai.toml`):
|
|
175
179
|
|
|
176
180
|
```toml
|
|
177
181
|
types = ["build", "ci", "docs", "chore"]
|
|
182
|
+
context_commits = 0 # disable commit context
|
|
178
183
|
```
|
|
179
184
|
|
|
180
185
|
Setting `types = []` restricts the AI to only the three mandatory types (`feat`, `fix`, `revert`).
|
|
181
186
|
|
|
187
|
+
`context_commits` controls how many recent commit messages are sent to the AI as context. The default is `5`. Set it to `0` to disable context entirely.
|
|
188
|
+
|
|
182
189
|
### Default optional types
|
|
183
190
|
|
|
184
191
|
| Type | Purpose |
|
|
@@ -208,11 +215,11 @@ Pushing a version tag (e.g. `v1.5.2`) triggers the CD pipeline:
|
|
|
208
215
|
# 1. Bump the version in pyproject.toml
|
|
209
216
|
# 2. Commit and push
|
|
210
217
|
git add pyproject.toml
|
|
211
|
-
git commit -m "chore: bump version to 2.
|
|
218
|
+
git commit -m "chore: bump version to 2.3.0"
|
|
212
219
|
git push origin main
|
|
213
220
|
# 3. Tag and push - this triggers the CD pipeline
|
|
214
|
-
git tag v2.
|
|
215
|
-
git push origin v2.
|
|
221
|
+
git tag v2.3.0
|
|
222
|
+
git push origin v2.3.0
|
|
216
223
|
```
|
|
217
224
|
|
|
218
225
|
## Debugging
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
git_commit_msg_ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
git_commit_msg_ai/ai_client.py,sha256=zgGrhVlLpTKkr4Z_7IbBvdJWIVObJvWCc8_DnUubiiY,3756
|
|
3
|
+
git_commit_msg_ai/cli.py,sha256=9RkXcTmeVn686b9F7upCgq8QQCpzHg8nnmwl1WpaqVg,3060
|
|
4
|
+
git_commit_msg_ai/config.py,sha256=5TqQR7VGzpev2_4a2tlsKD00tdFeOoJ1_XDIBhy_gDA,4513
|
|
5
|
+
git_commit_msg_ai/editor.py,sha256=wW7TJ4zVvvN7ThLtrJthAf9FjdmIDTbBS7V5pIW490s,2143
|
|
6
|
+
git_commit_msg_ai/exceptions.py,sha256=7Hwluf3zHMjs4lpGktWS-Lwgo8y_4Xbb1WqzPQHkkUA,352
|
|
7
|
+
git_commit_msg_ai/git_ops.py,sha256=Ve4ngXj0B3sYI4fKjIm-jKKe982Ohr9nbv1ZhNRGWFk,2329
|
|
8
|
+
git_commit_msg_ai-2.3.0.dist-info/licenses/LICENSE,sha256=BBR2CbV1SRenzTi4vvRx5wTIg32q898vdAyaLDN5wDc,1068
|
|
9
|
+
git_commit_msg_ai-2.3.0.dist-info/METADATA,sha256=EMAfQQAYvBnhM5jheLvG4dxqhS0zORFCExr-8m3dExg,9094
|
|
10
|
+
git_commit_msg_ai-2.3.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
11
|
+
git_commit_msg_ai-2.3.0.dist-info/entry_points.txt,sha256=KTu6wUhl0p3nf27k8L4vpSH_hpeRQpwzMPSmKv7K5Cs,65
|
|
12
|
+
git_commit_msg_ai-2.3.0.dist-info/top_level.txt,sha256=XYQC2BXvrcREGKEG7sm9nbwO7ifqcUSVgU7SW8BTURs,18
|
|
13
|
+
git_commit_msg_ai-2.3.0.dist-info/RECORD,,
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
git_commit_msg_ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
git_commit_msg_ai/ai_client.py,sha256=7B4bBrh9ZSd-1uChccnK3KYPnk9tXs9gOez5ASC5P54,2836
|
|
3
|
-
git_commit_msg_ai/cli.py,sha256=MzFQWHLAcheg7ldWwDQG05KcAQeIjlKtiEmcSKzvDUk,2049
|
|
4
|
-
git_commit_msg_ai/config.py,sha256=auD_QRw-8ngRz2p1DT5L5G5riszegZItSasmczv5W2s,2523
|
|
5
|
-
git_commit_msg_ai/editor.py,sha256=wW7TJ4zVvvN7ThLtrJthAf9FjdmIDTbBS7V5pIW490s,2143
|
|
6
|
-
git_commit_msg_ai/exceptions.py,sha256=7Hwluf3zHMjs4lpGktWS-Lwgo8y_4Xbb1WqzPQHkkUA,352
|
|
7
|
-
git_commit_msg_ai/git_ops.py,sha256=qZae4w3IEf3Lmf2T5oWItkgM0PrEYHCWr3TgBJLeecY,1387
|
|
8
|
-
git_commit_msg_ai-2.1.2.dist-info/licenses/LICENSE,sha256=BBR2CbV1SRenzTi4vvRx5wTIg32q898vdAyaLDN5wDc,1068
|
|
9
|
-
git_commit_msg_ai-2.1.2.dist-info/METADATA,sha256=ruzgyY3xmA2u6xkvbEZI2jbC0Jm7jXhqIGHjKkJCO2w,8310
|
|
10
|
-
git_commit_msg_ai-2.1.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
11
|
-
git_commit_msg_ai-2.1.2.dist-info/entry_points.txt,sha256=KTu6wUhl0p3nf27k8L4vpSH_hpeRQpwzMPSmKv7K5Cs,65
|
|
12
|
-
git_commit_msg_ai-2.1.2.dist-info/top_level.txt,sha256=XYQC2BXvrcREGKEG7sm9nbwO7ifqcUSVgU7SW8BTURs,18
|
|
13
|
-
git_commit_msg_ai-2.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|