commit-maker 0.1.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Alex Bulgakov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,127 @@
1
+ Metadata-Version: 2.1
2
+ Name: commit_maker
3
+ Version: 0.1.0
4
+ Summary: CLI-утилита для генерации git-коммитов с помощью ИИ
5
+ Author: Alex Bulgakov
6
+ Author-email: Alex Bulgakov <sashayerty@ya.ru>
7
+ License: MIT
8
+ Requires-Python: >=3.8
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: setuptools>=75.3.2
12
+ Requires-Dist: twine>=6.1.0
13
+
14
+ # Commit Maker [![Created with Python](https://img.shields.io/badge/Created_with-Python-blue)](https://www.python.org/) [![Created with uv](https://img.shields.io/badge/Created_with-uv-purple)](https://docs.astral.sh/uv/) [![Created with ollama](https://img.shields.io/badge/Created_with-ollama-white)](https://ollama.com/)
15
+
16
+ ![Демонстрация](./commit_maker.svg)
17
+
18
+ ## Все коммиты в репозитории - результат работы программы
19
+
20
+ Эта CLI-утилита автоматически создает осмысленные сообщения для git-коммитов, используя локальные модели через ollama/Mistral AI API на основе вывода команд `git status` и `git diff`. Реализована в виде одного файла для удобства перевода в исполняемый файл.
21
+
22
+ 1. [Возможности](#возможности)
23
+ 2. [Требования](#требования)
24
+ - [Mistral](#получение-api-ключа-mistral-ai)
25
+ - [Ollama](#установка-ollama)
26
+ 3. [Установка](#установка)
27
+ 4. [Настройка переменных окружения](#настройка-переменных-окружения)
28
+ - [Windows](#windows)
29
+ - [Linux/MacOS](#linuxmacos)
30
+ 5. [Использование](#использование)
31
+ 6. [Примечания](#примечания)
32
+ 7. [Лицензия](#лицензия)
33
+
34
+ ## Возможности
35
+
36
+ - Автоматически генерирует содержательные сообщения коммитов на русском языке
37
+ - Интерактивное подтверждение перед созданием коммита
38
+ - Работает как с существующими Git-репозиториями, так и с новыми
39
+ - Использование локальных моделей/Mistral AI API для формирования сообщений коммитов на основе изменений в репозитории.
40
+
41
+ ## Требования
42
+
43
+ - Установленный Git в системе
44
+ - API-ключ Mistral (для использования Mistral AI API)
45
+ - Установленная ollama в системе (для использования локальных моделей)
46
+
47
+ ### Получение API ключа Mistral AI
48
+
49
+ Для получения ключа необходимо перейти сайт консоли [Mistral](https://console.mistral.ai/api-keys) и создать API ключ. Для получения необходим аккаунт [Mistral](https://auth.mistral.ai/ui/login).
50
+
51
+ ### Установка ollama
52
+
53
+ Для установки ollama переходим на сайт [Ollama](https://ollama.com/download) и выбираем способ, подходящий для Вашей системы.
54
+
55
+ ## Установка
56
+
57
+ ```bash
58
+ # Windows
59
+ pip install git+https://github.com/sashayerty/commit_maker
60
+ # Linux/MacOS
61
+ pip3 install git+https://github.com/sashayerty/commit_maker
62
+ ```
63
+
64
+ ## Настройка переменных окружения
65
+
66
+ ### Windows
67
+
68
+ 1. Откройте Командную строку от имени Администратора
69
+ 2. Установите API-ключ Mistral:
70
+
71
+ ```cmd
72
+ setx MISTRAL_API_KEY "ваш_api_ключ_здесь"
73
+ ```
74
+
75
+ 3. Перезапустите терминал/IDE для применения изменений
76
+
77
+ ### Linux/macOS
78
+
79
+ 1. Откройте терминал
80
+ 2. Добавьте в файл конфигурации вашей оболочки (`~/.bashrc`, `~/.zshrc` или `~/.bash_profile`):
81
+
82
+ ```bash
83
+ export MISTRAL_API_KEY="ваш_api_ключ_здесь"
84
+ ```
85
+
86
+ 3. Перезагрузите конфигурацию:
87
+
88
+ ```bash
89
+ source ~/.bashrc # или другой файл, который вы редактировали
90
+ ```
91
+
92
+ ## Использование
93
+
94
+ ### Windows
95
+
96
+ ```cmd
97
+ commit_maker.exe [OPTION] [VALUE]
98
+ ```
99
+
100
+ ### Linux/MacOS
101
+
102
+ ```bash
103
+ commit_maker [OPTION] [VALUE]
104
+ ```
105
+
106
+ ### Пример использования
107
+
108
+ **`-h`**, **`--help`** - вывод помощи
109
+ **`-l`**, **`--local-models`** - использование локальных моделей
110
+ **`-m`**, **`--max-symbols`** - ограничение длины сообщения коммита
111
+ **`-M`**, **`--model`** - какую локальную модель использовать (при **`-l`**)
112
+ **`-d`**, **`--dry-run`** - вывод сообщения на основе зайстейдженных изменений, без создания коммита
113
+
114
+ ```bash
115
+ commit_maker -l -m 300 -M qwen2.5:14b # Используем локальные модели, ограничение длины сообщения коммита 300 символов, используем qwen2.5:14b
116
+ ```
117
+
118
+ ## Примечания
119
+
120
+ - Для просмотра всех возможных опций выполнения скрипта добавьте флаг `--help`
121
+ - Скрипт покажет сгенерированное сообщение коммита перед его созданием
122
+ - Вы можете повторно сгенерировать сообщение, нажав 'r' при запросе подтверждения
123
+ - По умолчанию сообщения генерируются на русском языке (можно изменить в скрипте)
124
+
125
+ ## Лицензия
126
+
127
+ Commit Maker лицензирован [MIT](LICENSE)
@@ -0,0 +1,114 @@
1
+ # Commit Maker [![Created with Python](https://img.shields.io/badge/Created_with-Python-blue)](https://www.python.org/) [![Created with uv](https://img.shields.io/badge/Created_with-uv-purple)](https://docs.astral.sh/uv/) [![Created with ollama](https://img.shields.io/badge/Created_with-ollama-white)](https://ollama.com/)
2
+
3
+ ![Демонстрация](./commit_maker.svg)
4
+
5
+ ## Все коммиты в репозитории - результат работы программы
6
+
7
+ Эта CLI-утилита автоматически создает осмысленные сообщения для git-коммитов, используя локальные модели через ollama/Mistral AI API на основе вывода команд `git status` и `git diff`. Реализована в виде одного файла для удобства перевода в исполняемый файл.
8
+
9
+ 1. [Возможности](#возможности)
10
+ 2. [Требования](#требования)
11
+ - [Mistral](#получение-api-ключа-mistral-ai)
12
+ - [Ollama](#установка-ollama)
13
+ 3. [Установка](#установка)
14
+ 4. [Настройка переменных окружения](#настройка-переменных-окружения)
15
+ - [Windows](#windows)
16
+ - [Linux/MacOS](#linuxmacos)
17
+ 5. [Использование](#использование)
18
+ 6. [Примечания](#примечания)
19
+ 7. [Лицензия](#лицензия)
20
+
21
+ ## Возможности
22
+
23
+ - Автоматически генерирует содержательные сообщения коммитов на русском языке
24
+ - Интерактивное подтверждение перед созданием коммита
25
+ - Работает как с существующими Git-репозиториями, так и с новыми
26
+ - Использование локальных моделей/Mistral AI API для формирования сообщений коммитов на основе изменений в репозитории.
27
+
28
+ ## Требования
29
+
30
+ - Установленный Git в системе
31
+ - API-ключ Mistral (для использования Mistral AI API)
32
+ - Установленная ollama в системе (для использования локальных моделей)
33
+
34
+ ### Получение API ключа Mistral AI
35
+
36
+ Для получения ключа необходимо перейти сайт консоли [Mistral](https://console.mistral.ai/api-keys) и создать API ключ. Для получения необходим аккаунт [Mistral](https://auth.mistral.ai/ui/login).
37
+
38
+ ### Установка ollama
39
+
40
+ Для установки ollama переходим на сайт [Ollama](https://ollama.com/download) и выбираем способ, подходящий для Вашей системы.
41
+
42
+ ## Установка
43
+
44
+ ```bash
45
+ # Windows
46
+ pip install git+https://github.com/sashayerty/commit_maker
47
+ # Linux/MacOS
48
+ pip3 install git+https://github.com/sashayerty/commit_maker
49
+ ```
50
+
51
+ ## Настройка переменных окружения
52
+
53
+ ### Windows
54
+
55
+ 1. Откройте Командную строку от имени Администратора
56
+ 2. Установите API-ключ Mistral:
57
+
58
+ ```cmd
59
+ setx MISTRAL_API_KEY "ваш_api_ключ_здесь"
60
+ ```
61
+
62
+ 3. Перезапустите терминал/IDE для применения изменений
63
+
64
+ ### Linux/macOS
65
+
66
+ 1. Откройте терминал
67
+ 2. Добавьте в файл конфигурации вашей оболочки (`~/.bashrc`, `~/.zshrc` или `~/.bash_profile`):
68
+
69
+ ```bash
70
+ export MISTRAL_API_KEY="ваш_api_ключ_здесь"
71
+ ```
72
+
73
+ 3. Перезагрузите конфигурацию:
74
+
75
+ ```bash
76
+ source ~/.bashrc # или другой файл, который вы редактировали
77
+ ```
78
+
79
+ ## Использование
80
+
81
+ ### Windows
82
+
83
+ ```cmd
84
+ commit_maker.exe [OPTION] [VALUE]
85
+ ```
86
+
87
+ ### Linux/MacOS
88
+
89
+ ```bash
90
+ commit_maker [OPTION] [VALUE]
91
+ ```
92
+
93
+ ### Пример использования
94
+
95
+ **`-h`**, **`--help`** - вывод помощи
96
+ **`-l`**, **`--local-models`** - использование локальных моделей
97
+ **`-m`**, **`--max-symbols`** - ограничение длины сообщения коммита
98
+ **`-M`**, **`--model`** - какую локальную модель использовать (при **`-l`**)
99
+ **`-d`**, **`--dry-run`** - вывод сообщения на основе зайстейдженных изменений, без создания коммита
100
+
101
+ ```bash
102
+ commit_maker -l -m 300 -M qwen2.5:14b # Используем локальные модели, ограничение длины сообщения коммита 300 символов, используем qwen2.5:14b
103
+ ```
104
+
105
+ ## Примечания
106
+
107
+ - Для просмотра всех возможных опций выполнения скрипта добавьте флаг `--help`
108
+ - Скрипт покажет сгенерированное сообщение коммита перед его созданием
109
+ - Вы можете повторно сгенерировать сообщение, нажав 'r' при запросе подтверждения
110
+ - По умолчанию сообщения генерируются на русском языке (можно изменить в скрипте)
111
+
112
+ ## Лицензия
113
+
114
+ Commit Maker лицензирован [MIT](LICENSE)
@@ -0,0 +1,21 @@
1
+ [project]
2
+ name = "commit_maker"
3
+ version = "0.1.0"
4
+ authors = [
5
+ { name="Alex Bulgakov", email="sashayerty@ya.ru" }
6
+ ]
7
+ description = "CLI-утилита для генерации git-коммитов с помощью ИИ"
8
+ readme = "README.md"
9
+ license = { text = "MIT" }
10
+ requires-python = ">=3.8"
11
+ dependencies = [
12
+ "setuptools>=75.3.2",
13
+ "twine>=6.1.0",
14
+ ]
15
+
16
+ [project.scripts]
17
+ commit_maker = "commit_maker.main:main"
18
+
19
+ [build-system]
20
+ requires = ["setuptools>=61.0"]
21
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,27 @@
1
+ from setuptools import find_packages, setup
2
+
3
+ setup(
4
+ name="commit_maker",
5
+ version="0.1.0",
6
+ author="Alex Bulgakov",
7
+ author_email="sashayerty@ya.ru",
8
+ description="CLI-утилита для генерации git-коммитов с помощью ИИ",
9
+ long_description=open("README.md", "r", encoding="utf-8").read(),
10
+ long_description_content_type="text/markdown",
11
+ license="MIT",
12
+ python_requires=">=3.8",
13
+ packages=find_packages(where="src"),
14
+ package_dir={"": "src"},
15
+ entry_points={
16
+ "console_scripts": [
17
+ "commit_maker=commit_maker.main:main",
18
+ ],
19
+ },
20
+ install_requires=[],
21
+ include_package_data=True,
22
+ classifiers=[
23
+ "Programming Language :: Python :: 3",
24
+ "License :: OSI Approved :: MIT License",
25
+ "Operating System :: OS Independent",
26
+ ],
27
+ )
File without changes
@@ -0,0 +1,556 @@
1
+ # CLI-утилита, которая будет создавать сообщение для коммита на основе ИИ.
2
+ # noqa: F841
3
+
4
+ import argparse
5
+ import json
6
+ import os
7
+ import subprocess
8
+ import urllib
9
+ import urllib.request
10
+
11
+ # Константы
12
+ mistral_api_key = os.environ["MISTRAL_API_KEY"]
13
+
14
+ # Для цветных логов
15
+ COLOR_RED = "\033[31m"
16
+ COLOR_GREEN = "\033[32m"
17
+ COLOR_YELLOW = "\033[33m"
18
+ COLOR_BLUE = "\033[94m"
19
+ COLOR_MAGENTA = "\033[95m"
20
+ COLOR_CYAN = "\033[96m"
21
+ COLOR_RESET = "\033[0m"
22
+ COLORS_DICT = {
23
+ "red": COLOR_RED,
24
+ "green": COLOR_GREEN,
25
+ "yellow": COLOR_YELLOW,
26
+ "blue": COLOR_BLUE,
27
+ "magenta": COLOR_MAGENTA,
28
+ "cyan": COLOR_CYAN,
29
+ "reset": COLOR_RESET,
30
+ }
31
+
32
+ # Парсер параметров
33
+ parser = argparse.ArgumentParser(
34
+ prog="Commit Maker",
35
+ usage="commit_maker [OPTION] [VALUE]",
36
+ description="CLI-утилита, которая будет создавать сообщение "
37
+ "для коммита на основе ИИ. Можно использовать локальные модели/Mistral AI "
38
+ "API. Локальные модели используют ollama.",
39
+ )
40
+ parser.add_argument(
41
+ "-l",
42
+ "--local-models",
43
+ action="store_true",
44
+ default=False,
45
+ help="Запуск с использованием локальных моделей",
46
+ )
47
+ parser.add_argument(
48
+ "-m",
49
+ "--max-symbols",
50
+ type=int,
51
+ default=250,
52
+ metavar="[max_symbols]",
53
+ help="Длина сообщения коммита. Defaults to 150",
54
+ )
55
+ parser.add_argument(
56
+ "-M",
57
+ "--model",
58
+ type=str,
59
+ metavar="[model]",
60
+ help="Модель, которую ollama будет использовать.",
61
+ )
62
+ parser.add_argument(
63
+ "-d",
64
+ "--dry-run",
65
+ action="store_true",
66
+ default=False,
67
+ help="Запуск с выводом сообщения на основе зайстейдженных "
68
+ "изменений, без создания коммита",
69
+ )
70
+
71
+ # Парсинг аргументов
72
+ parsed_args = parser.parse_args()
73
+ use_local_models = parsed_args.local_models
74
+ max_symbols = parsed_args.max_symbols
75
+ model = parsed_args.model
76
+ dry_run = parsed_args.dry_run
77
+
78
+ # Промпт для ИИ
79
+ prompt_for_ai = f"""Привет! Ты составитель коммитов для git.
80
+ Сгенерируй коммит-месседж на РУССКОМ языке, который:
81
+ 1. Точно отражает суть изменений
82
+ 2. Не превышает {max_symbols} символов
83
+ Опирайся на данные от 'git status' и 'git diff'.
84
+ В ответ на это сообщение тебе нужно предоставить
85
+ ТОЛЬКО коммит. Пиши просто обычный текст, без markdown!"""
86
+
87
+
88
+ # Класс для использования API Mistral AI
89
+ class MistralAI:
90
+ """Класс для общения с MistralAI. Написан с помощью urllib."""
91
+
92
+ def __init__(self, api_key: str):
93
+ """Инициализация класса
94
+
95
+ Args:
96
+ api_key (str): Апи ключ MistralAI
97
+ """
98
+ self.url = "https://api.mistral.ai/v1/chat/completions"
99
+ self.api_key = api_key
100
+ self.headers = {
101
+ "Content-Type": "application/json",
102
+ "Accept": "application/json",
103
+ "Authorization": f"Bearer {api_key}",
104
+ }
105
+ self.data = {
106
+ "model": "mistral-small-latest",
107
+ "messages": [],
108
+ "temperature": 0.7,
109
+ }
110
+
111
+ def message(
112
+ self,
113
+ message: str,
114
+ role: str = "user",
115
+ temperature: float = 0.7,
116
+ ) -> str:
117
+ """Функция сообщения
118
+
119
+ Args:
120
+ message (str): Сообщение
121
+ role (str, optional): Роль. Defaults to "user".
122
+
123
+ Returns:
124
+ str: Json-ответ/Err
125
+ """
126
+ self.data["messages"] = [
127
+ {
128
+ "role": role,
129
+ "content": message,
130
+ }
131
+ ]
132
+ post_data = json.dumps(self.data).encode("utf-8")
133
+ request = urllib.request.Request(
134
+ url=self.url,
135
+ data=post_data,
136
+ headers=self.headers,
137
+ method="POST",
138
+ )
139
+ try:
140
+ with urllib.request.urlopen(request) as response:
141
+ if response.status == 200:
142
+ response_data = json.loads(response.read().decode())
143
+ return response_data["choices"][0]["message"]["content"]
144
+ else:
145
+ print(f"Ошибка: {response.status}")
146
+ except urllib.error.URLError as e:
147
+ print(f"Ошибка URL: {e.reason}")
148
+ except urllib.error.HTTPError as e:
149
+ print(f"Ошибка HTTP: {e.code} {e.reason}")
150
+ print(f"Ответ сервера: {e.read().decode()}")
151
+
152
+
153
+ # Класс для использования API Ollama
154
+ class Ollama:
155
+ """Класс для общения с локальными моделями Ollama.
156
+ Написан с помощью urllib."""
157
+
158
+ def __init__(
159
+ self,
160
+ model: str,
161
+ ):
162
+ """Инициализация класса"""
163
+ self.model = model
164
+ self.url = "http://localhost:11434/api/chat"
165
+ self.headers = {
166
+ "Content-Type": "application/json",
167
+ "Accept": "application/json",
168
+ }
169
+
170
+ def message(
171
+ self,
172
+ message: str,
173
+ temperature: float = 0.7,
174
+ role: str = "user",
175
+ ) -> str:
176
+ """Функция сообщения
177
+
178
+ Args:
179
+ message (str): Сообщение
180
+ model (str): Модель, с которой будем общаться
181
+ temperature (float, optional): Температура общения. Defaults to 0.7
182
+ role (str, optional): Роль в сообщении.
183
+
184
+ Returns:
185
+ str: Json-ответ/Err
186
+ """
187
+ self.data = {
188
+ "model": self.model,
189
+ "messages": [
190
+ {
191
+ "role": role,
192
+ "content": message,
193
+ }
194
+ ],
195
+ "options": {
196
+ "temperature": temperature,
197
+ },
198
+ "stream": False,
199
+ }
200
+ post_data = json.dumps(self.data).encode("utf-8")
201
+ request = urllib.request.Request(
202
+ url=self.url,
203
+ data=post_data,
204
+ headers=self.headers,
205
+ method="POST",
206
+ )
207
+ try:
208
+ with urllib.request.urlopen(request) as response:
209
+ if response.status == 200:
210
+ response_data = json.loads(response.read().decode())
211
+ return response_data["message"]["content"]
212
+ else:
213
+ print(f"Ошибка: {response.status}")
214
+ except urllib.error.URLError as e:
215
+ print(f"Ошибка URL: {e.reason}")
216
+ except urllib.error.HTTPError as e:
217
+ print(f"Ошибка HTTP: {e.code} {e.reason}")
218
+ print(f"Ответ сервера: {e.read().decode()}")
219
+
220
+
221
+ def bold(text: str) -> str:
222
+ """Возвращает жирный текст
223
+
224
+ Args:
225
+ text (str): Текст
226
+
227
+ Returns:
228
+ str: Жирный текст
229
+ """
230
+ bold_start = "\033[1m"
231
+ bold_end = "\033[0m"
232
+ return f"{bold_start}{text}{bold_end}"
233
+
234
+
235
+ def colored(
236
+ string: str,
237
+ color: str,
238
+ text_bold: bool = True,
239
+ ) -> str:
240
+ """Функция для 'окраски' строк для красивого вывода
241
+
242
+ Args:
243
+ string (str): Строка, которую нужно покрасить
244
+ color (str): Цвет покраски ['red', 'yellow', 'green', 'magenta',\
245
+ 'blue', 'cyan', 'reset']
246
+ text_bold (bool, optional): Жирный текст или нет. Defaults to True.
247
+
248
+ Returns:
249
+ str: Покрашенная строка
250
+
251
+ Example:
252
+ `print(colored(string='Success!', color='green'))` # Выводит 'Success!'
253
+ зеленого цвета
254
+ """
255
+ global COLORS_DICT
256
+ return (
257
+ bold(f"{COLORS_DICT[color]}{string}{COLORS_DICT['reset']}")
258
+ if text_bold
259
+ else f"{COLORS_DICT[color]}{string}{COLORS_DICT['reset']}"
260
+ )
261
+
262
+
263
+ # main функция
264
+
265
+
266
+ def main() -> None:
267
+ global mistral_api_key, prompt_for_ai, use_local_models, model, dry_run
268
+ try:
269
+ # Получаем версию git, если он есть
270
+ git_version = subprocess.run( # noqa
271
+ ["git", "--version"],
272
+ capture_output=True,
273
+ text=True,
274
+ encoding="utf-8",
275
+ ).stdout
276
+
277
+ # Получаем список моделей из Ollama, если Ollama есть
278
+ ollama_list_of_models = (
279
+ subprocess.run(
280
+ ["ollama", "ls"],
281
+ capture_output=True,
282
+ text=True,
283
+ encoding="utf-8",
284
+ )
285
+ .stdout.strip()
286
+ .split("\n")
287
+ )
288
+ ollama_list_of_models = [
289
+ i.split()[0] for i in ollama_list_of_models[1:]
290
+ ]
291
+
292
+ # Обработка отсутствия ollama
293
+ if not ollama_list_of_models and use_local_models:
294
+ print(
295
+ colored(
296
+ "Ollama не установлена или список моделей пуст!", "yellow"
297
+ )
298
+ + " Для установки перейдите по https://ollama.com/download"
299
+ )
300
+ return None
301
+ elif not use_local_models and model:
302
+ print(
303
+ f"Для использования {model} локально используйте флаг "
304
+ + colored("--local-models", "yellow")
305
+ + ". Если нужна помощь: "
306
+ + colored("--help", "yellow")
307
+ )
308
+ return None
309
+ elif ollama_list_of_models and use_local_models:
310
+ if not model:
311
+ if len(ollama_list_of_models) > 1:
312
+ print(
313
+ colored(
314
+ "Для использования локальных моделей необходимо "
315
+ "выбрать модель:",
316
+ "yellow",
317
+ )
318
+ + "\n"
319
+ + "\n".join(
320
+ [
321
+ f"{i + 1}. {colored(model, 'magenta', False,)}"
322
+ for i, model in enumerate(
323
+ ollama_list_of_models
324
+ )
325
+ ]
326
+ )
327
+ )
328
+ model_is_selected = False
329
+ while not model_is_selected:
330
+ model = input(
331
+ colored(
332
+ "Введите число от 1 до "
333
+ f"{len(ollama_list_of_models)}: ",
334
+ "yellow",
335
+ )
336
+ )
337
+ model = int(model) if model.isdigit() else -1
338
+ if model > len(ollama_list_of_models) or model == -1:
339
+ continue
340
+ model = ollama_list_of_models[model - 1]
341
+ model_is_selected = True
342
+ break
343
+ else:
344
+ model = ollama_list_of_models[0]
345
+ else:
346
+ if model not in ollama_list_of_models:
347
+ print(
348
+ colored(
349
+ f"{model} не является доступной моделью! ", "red"
350
+ )
351
+ + "Доступные модели: "
352
+ + colored(
353
+ f"{', '.join(ollama_list_of_models)}", "yellow"
354
+ )
355
+ )
356
+ return None
357
+ if model:
358
+ print("Выбрана модель: " + colored(model, "yellow"))
359
+
360
+ # Проверяем, есть ли .git
361
+ dot_git = ".git" in os.listdir("./")
362
+
363
+ # Если есть
364
+ if dot_git:
365
+ # Получаем разницу в коммитах
366
+ git_status = subprocess.run(
367
+ ["git", "status", "-v"],
368
+ capture_output=True,
369
+ text=True,
370
+ encoding="utf-8",
371
+ )
372
+
373
+ new_files = subprocess.run(
374
+ ["git", "ls-files", "--others", "--exclude-standard"],
375
+ capture_output=True,
376
+ text=True,
377
+ encoding="utf-8",
378
+ )
379
+
380
+ git_diff = subprocess.run(
381
+ ["git", "diff", "--staged"],
382
+ capture_output=True,
383
+ text=True,
384
+ encoding="utf-8",
385
+ )
386
+ if (
387
+ (not new_files.stdout)
388
+ and (not git_diff.stdout)
389
+ and (
390
+ not subprocess.run(
391
+ ["git", "diff"],
392
+ capture_output=True,
393
+ encoding="utf-8",
394
+ ).stdout
395
+ )
396
+ ): # Проверка на отсутствие каких-либо изменений
397
+ print(colored("Нет добавленных изменений!", "red"))
398
+ return None
399
+ if not git_diff.stdout:
400
+ if not dry_run:
401
+ if (
402
+ input(
403
+ colored("Нет застейдженных изменений!", "red")
404
+ + " Добавить всё автоматически с помощью "
405
+ + colored("git add -A", "yellow")
406
+ + "? [y/N]: "
407
+ )
408
+ == "y"
409
+ ):
410
+ subprocess.run(
411
+ ["git", "add", "-A"],
412
+ capture_output=True,
413
+ encoding="utf-8",
414
+ )
415
+ else:
416
+ print(
417
+ colored(
418
+ "Добавьте необходимые файлы вручную.", "yellow"
419
+ )
420
+ )
421
+ return None
422
+ else:
423
+ print(
424
+ colored("Нечего коммитить!", "red")
425
+ + " Добавьте необходимые файлы с помощью "
426
+ + colored("git add <filename>", "yellow")
427
+ )
428
+ return None
429
+ git_diff = subprocess.run(
430
+ ["git", "diff", "--staged"],
431
+ capture_output=True,
432
+ text=True,
433
+ encoding="utf-8",
434
+ )
435
+ if subprocess.run(
436
+ ["git", "diff"],
437
+ capture_output=True,
438
+ encoding="utf-8",
439
+ ).stdout:
440
+ print(
441
+ colored(
442
+ "Обратите внимание на то, что у Вас "
443
+ "есть незастейдженные изменения!",
444
+ "red",
445
+ )
446
+ + " Для добавления дополнительных файлов "
447
+ + colored("Ctrl + C", "yellow")
448
+ + " и выполните "
449
+ + colored("git add <filename>", "yellow")
450
+ + "."
451
+ )
452
+ if use_local_models:
453
+ client = Ollama(model=model)
454
+ else:
455
+ client = MistralAI(
456
+ api_key=mistral_api_key,
457
+ )
458
+ if not dry_run:
459
+ retry = True
460
+ while retry:
461
+ commit_message = client.message(
462
+ message=prompt_for_ai
463
+ + "Git status: "
464
+ + git_status.stdout
465
+ + "Git diff: "
466
+ + git_diff.stdout,
467
+ temperature=1.0,
468
+ )
469
+ commit_with_message_from_ai = input(
470
+ "Закоммитить с сообщением "
471
+ + colored(f"'{commit_message}'", "yellow")
472
+ + "? [y/N/r]: "
473
+ )
474
+ if commit_with_message_from_ai != "r":
475
+ retry = False
476
+ break
477
+ if commit_with_message_from_ai == "y":
478
+ subprocess.run(
479
+ ["git", "commit", "-m", f"{commit_message}"],
480
+ encoding="utf-8",
481
+ )
482
+ print(colored("Коммит успешно создан!", "green"))
483
+ else:
484
+ commit_message = client.message(
485
+ message=prompt_for_ai
486
+ + "Git status: "
487
+ + git_status.stdout
488
+ + "Git diff: "
489
+ + git_diff.stdout,
490
+ temperature=1.0,
491
+ )
492
+ print(
493
+ colored(
494
+ "Коммит-месседж успешно сгенерирован:", "green", False
495
+ )
496
+ )
497
+ print(
498
+ colored(
499
+ commit_message,
500
+ "yellow",
501
+ False,
502
+ )
503
+ )
504
+ return None
505
+
506
+ # Если нет
507
+ else:
508
+ init_git_repo = (
509
+ True
510
+ if input(
511
+ colored("Не инициализирован git репозиторий!", "red")
512
+ + " Выполнить "
513
+ + colored("git init", "yellow")
514
+ + "? [y/N]: "
515
+ )
516
+ == "y"
517
+ else False
518
+ )
519
+ if init_git_repo:
520
+ subprocess.run(
521
+ ["git", "init"],
522
+ capture_output=True,
523
+ encoding="utf-8",
524
+ )
525
+
526
+ (
527
+ (
528
+ subprocess.run(
529
+ ["git", "add", "-A"],
530
+ capture_output=True,
531
+ encoding="utf-8",
532
+ ),
533
+ subprocess.run(
534
+ [
535
+ "git",
536
+ "commit",
537
+ "-m",
538
+ "'Initial commit'",
539
+ ],
540
+ encoding="utf-8",
541
+ ),
542
+ )
543
+ if input(
544
+ "Сделать первый коммит с сообщением "
545
+ + colored("'Initial commit?'", "yellow")
546
+ + " [y/N]: "
547
+ )
548
+ == "y"
549
+ else None
550
+ )
551
+ except Exception as e:
552
+ print(colored("Ошибка:", "red") + " " + str(e))
553
+
554
+
555
+ if __name__ == "__main__":
556
+ main()
@@ -0,0 +1,127 @@
1
+ Metadata-Version: 2.1
2
+ Name: commit_maker
3
+ Version: 0.1.0
4
+ Summary: CLI-утилита для генерации git-коммитов с помощью ИИ
5
+ Author: Alex Bulgakov
6
+ Author-email: Alex Bulgakov <sashayerty@ya.ru>
7
+ License: MIT
8
+ Requires-Python: >=3.8
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: setuptools>=75.3.2
12
+ Requires-Dist: twine>=6.1.0
13
+
14
+ # Commit Maker [![Created with Python](https://img.shields.io/badge/Created_with-Python-blue)](https://www.python.org/) [![Created with uv](https://img.shields.io/badge/Created_with-uv-purple)](https://docs.astral.sh/uv/) [![Created with ollama](https://img.shields.io/badge/Created_with-ollama-white)](https://ollama.com/)
15
+
16
+ ![Демонстрация](./commit_maker.svg)
17
+
18
+ ## Все коммиты в репозитории - результат работы программы
19
+
20
+ Эта CLI-утилита автоматически создает осмысленные сообщения для git-коммитов, используя локальные модели через ollama/Mistral AI API на основе вывода команд `git status` и `git diff`. Реализована в виде одного файла для удобства перевода в исполняемый файл.
21
+
22
+ 1. [Возможности](#возможности)
23
+ 2. [Требования](#требования)
24
+ - [Mistral](#получение-api-ключа-mistral-ai)
25
+ - [Ollama](#установка-ollama)
26
+ 3. [Установка](#установка)
27
+ 4. [Настройка переменных окружения](#настройка-переменных-окружения)
28
+ - [Windows](#windows)
29
+ - [Linux/MacOS](#linuxmacos)
30
+ 5. [Использование](#использование)
31
+ 6. [Примечания](#примечания)
32
+ 7. [Лицензия](#лицензия)
33
+
34
+ ## Возможности
35
+
36
+ - Автоматически генерирует содержательные сообщения коммитов на русском языке
37
+ - Интерактивное подтверждение перед созданием коммита
38
+ - Работает как с существующими Git-репозиториями, так и с новыми
39
+ - Использование локальных моделей/Mistral AI API для формирования сообщений коммитов на основе изменений в репозитории.
40
+
41
+ ## Требования
42
+
43
+ - Установленный Git в системе
44
+ - API-ключ Mistral (для использования Mistral AI API)
45
+ - Установленная ollama в системе (для использования локальных моделей)
46
+
47
+ ### Получение API ключа Mistral AI
48
+
49
+ Для получения ключа необходимо перейти сайт консоли [Mistral](https://console.mistral.ai/api-keys) и создать API ключ. Для получения необходим аккаунт [Mistral](https://auth.mistral.ai/ui/login).
50
+
51
+ ### Установка ollama
52
+
53
+ Для установки ollama переходим на сайт [Ollama](https://ollama.com/download) и выбираем способ, подходящий для Вашей системы.
54
+
55
+ ## Установка
56
+
57
+ ```bash
58
+ # Windows
59
+ pip install git+https://github.com/sashayerty/commit_maker
60
+ # Linux/MacOS
61
+ pip3 install git+https://github.com/sashayerty/commit_maker
62
+ ```
63
+
64
+ ## Настройка переменных окружения
65
+
66
+ ### Windows
67
+
68
+ 1. Откройте Командную строку от имени Администратора
69
+ 2. Установите API-ключ Mistral:
70
+
71
+ ```cmd
72
+ setx MISTRAL_API_KEY "ваш_api_ключ_здесь"
73
+ ```
74
+
75
+ 3. Перезапустите терминал/IDE для применения изменений
76
+
77
+ ### Linux/macOS
78
+
79
+ 1. Откройте терминал
80
+ 2. Добавьте в файл конфигурации вашей оболочки (`~/.bashrc`, `~/.zshrc` или `~/.bash_profile`):
81
+
82
+ ```bash
83
+ export MISTRAL_API_KEY="ваш_api_ключ_здесь"
84
+ ```
85
+
86
+ 3. Перезагрузите конфигурацию:
87
+
88
+ ```bash
89
+ source ~/.bashrc # или другой файл, который вы редактировали
90
+ ```
91
+
92
+ ## Использование
93
+
94
+ ### Windows
95
+
96
+ ```cmd
97
+ commit_maker.exe [OPTION] [VALUE]
98
+ ```
99
+
100
+ ### Linux/MacOS
101
+
102
+ ```bash
103
+ commit_maker [OPTION] [VALUE]
104
+ ```
105
+
106
+ ### Пример использования
107
+
108
+ **`-h`**, **`--help`** - вывод помощи
109
+ **`-l`**, **`--local-models`** - использование локальных моделей
110
+ **`-m`**, **`--max-symbols`** - ограничение длины сообщения коммита
111
+ **`-M`**, **`--model`** - какую локальную модель использовать (при **`-l`**)
112
+ **`-d`**, **`--dry-run`** - вывод сообщения на основе зайстейдженных изменений, без создания коммита
113
+
114
+ ```bash
115
+ commit_maker -l -m 300 -M qwen2.5:14b # Используем локальные модели, ограничение длины сообщения коммита 300 символов, используем qwen2.5:14b
116
+ ```
117
+
118
+ ## Примечания
119
+
120
+ - Для просмотра всех возможных опций выполнения скрипта добавьте флаг `--help`
121
+ - Скрипт покажет сгенерированное сообщение коммита перед его созданием
122
+ - Вы можете повторно сгенерировать сообщение, нажав 'r' при запросе подтверждения
123
+ - По умолчанию сообщения генерируются на русском языке (можно изменить в скрипте)
124
+
125
+ ## Лицензия
126
+
127
+ Commit Maker лицензирован [MIT](LICENSE)
@@ -0,0 +1,12 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ setup.py
5
+ src/commit_maker/__init__.py
6
+ src/commit_maker/main.py
7
+ src/commit_maker.egg-info/PKG-INFO
8
+ src/commit_maker.egg-info/SOURCES.txt
9
+ src/commit_maker.egg-info/dependency_links.txt
10
+ src/commit_maker.egg-info/entry_points.txt
11
+ src/commit_maker.egg-info/requires.txt
12
+ src/commit_maker.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ commit_maker = commit_maker.main:main
@@ -0,0 +1,2 @@
1
+ setuptools>=75.3.2
2
+ twine>=6.1.0
@@ -0,0 +1 @@
1
+ commit_maker