@notyped/gitai 0.0.11
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.
- package/README.md +531 -0
- package/dist/index.js +129 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
# Gitai - Automated Conventional Commits in Git with AI
|
|
2
|
+
|
|
3
|
+
Choose your language / Escolha o idioma:
|
|
4
|
+
|
|
5
|
+
- πΊπΈ [English](#-english)
|
|
6
|
+
- π§π· [PortuguΓͺs](#-portuguΓͺs)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# πΊπΈ English
|
|
11
|
+
|
|
12
|
+
[](https://github.com/leandrosilvaferreira/gitai-js/releases)
|
|
13
|
+
[](https://star-history.com/#leandrosilvaferreira/gitai-js)
|
|
14
|
+
[](https://github.com/leandrosilvaferreira/gitai-js/fork)
|
|
15
|
+
|
|
16
|
+
Gitai is a TypeScript/Node.js project that serves as an automation tool for managing Git commits. It is designed to analyze projects written in various programming languages, including Node.js, Python, Java, Go, and PHP.
|
|
17
|
+
|
|
18
|
+
The application analyzes the changes made in a project, identifies the programming language used, and based on that, generates a detailed commit message following the Conventional Commits standard. This standard is widely adopted to make commit messages more descriptive and useful.
|
|
19
|
+
|
|
20
|
+
Additionally, Gitai automates the commit process by adding all changes to the Git staging area, committing with the generated message, and optionally pushing the changes to the remote repository.
|
|
21
|
+
|
|
22
|
+
For generating the commit message, you can choose between the advanced language models from `OpenAI`, `Groq`, or `Anthropic`.
|
|
23
|
+
|
|
24
|
+
## π₯ Video Tutorial
|
|
25
|
+
|
|
26
|
+
Click the image below to watch the video tutorial about Gitai:
|
|
27
|
+
|
|
28
|
+
[](https://www.youtube.com/watch?v=GAQ4mmGxg7c "AUTOMATED GIT COMMITS WITH AI: GITAI (OPEN SOURCE AND FREE)")
|
|
29
|
+
|
|
30
|
+
## β‘ Installing the Application
|
|
31
|
+
|
|
32
|
+
Gitai can be installed globally via npm, making it available across all your projects:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g gitai
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
After installation, the `gitai` command will be available in your terminal.
|
|
39
|
+
|
|
40
|
+
## π€ Choosing the AI Model
|
|
41
|
+
|
|
42
|
+
Gitai supports three AI providers for generating commit messages: `OpenAI`, `Groq`, and `Anthropic`.
|
|
43
|
+
|
|
44
|
+
Each has its own characteristics, costs, and usage limits.
|
|
45
|
+
|
|
46
|
+
All providers are highly capable, but your choice may depend on your specific needs and available budget.
|
|
47
|
+
|
|
48
|
+
If you need high processing power and can cover the costs, OpenAI is an excellent option. If you prefer a free service and can manage within usage limits, Groq is a viable alternative. For advanced reasoning and large context windows, Anthropic Claude offers cutting-edge capabilities.
|
|
49
|
+
|
|
50
|
+
Below is detailed information about each provider to help you choose the best one for your needs.
|
|
51
|
+
|
|
52
|
+
### OpenAI
|
|
53
|
+
|
|
54
|
+
OpenAI is a paid service that offers advanced language models.
|
|
55
|
+
|
|
56
|
+
The most efficient available model is `gpt-4o`, which has a context window of 128K tokens.
|
|
57
|
+
|
|
58
|
+
- **Cost**:
|
|
59
|
+
- $2.50 per 1M tokens for Input
|
|
60
|
+
- $10.00 per 1M tokens for Output
|
|
61
|
+
- **Website**: [OpenAI](https://platform.openai.com/docs/introduction)
|
|
62
|
+
|
|
63
|
+
### Groq
|
|
64
|
+
|
|
65
|
+
Groq is a free service, but with usage limits.
|
|
66
|
+
|
|
67
|
+
The recommended model is `mixtral-8x7b-32768`, which offers a context window of 32,768 tokens.
|
|
68
|
+
|
|
69
|
+
- **Usage Limits**:
|
|
70
|
+
- **Requests per Minute**: 30
|
|
71
|
+
- **Requests per Day**: 14,400
|
|
72
|
+
- **Tokens per Minute**: 5,000
|
|
73
|
+
- **Website**: [Groq](https://console.groq.com/)
|
|
74
|
+
|
|
75
|
+
### Anthropic
|
|
76
|
+
|
|
77
|
+
Anthropic is a paid service that offers advanced AI models with excellent reasoning capabilities.
|
|
78
|
+
|
|
79
|
+
The recommended model is `claude-3-5-sonnet-20241022`, which has a context window of 200K tokens.
|
|
80
|
+
|
|
81
|
+
- **Cost**:
|
|
82
|
+
- $3.00 per 1M tokens for Input
|
|
83
|
+
- $15.00 per 1M tokens for Output
|
|
84
|
+
- **Features**: Advanced reasoning, large context window, excellent code understanding
|
|
85
|
+
- **Website**: [Anthropic](https://console.anthropic.com/)
|
|
86
|
+
|
|
87
|
+
## π± First-Time Setup
|
|
88
|
+
|
|
89
|
+
The first time you run `gitai`, a friendly **Setup Wizard** will launch automatically to help you configure your preferred AI provider, API key, model, and language.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
gitai
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The wizard will guide you through:
|
|
96
|
+
|
|
97
|
+
1. **Language Selection**: Choose your preferred language (English, Portuguese, Spanish, etc.)
|
|
98
|
+
2. **Provider Selection**: Choose between OpenAI, Groq, or Anthropic
|
|
99
|
+
3. **API Key**: Enter your API key for the selected provider
|
|
100
|
+
4. **Model Selection**: Choose the AI model to use (e.g., `gpt-4o`, `mixtral-8x7b-32768`, `claude-3-5-sonnet-20241022`)
|
|
101
|
+
|
|
102
|
+
Your configuration is saved globally in `~/.gitai`, so you don't need to configure it for every project.
|
|
103
|
+
|
|
104
|
+
### Example configuration for OpenAI
|
|
105
|
+
|
|
106
|
+
```dotenv
|
|
107
|
+
PROVIDER=openai
|
|
108
|
+
API_KEY=your_openai_api_key
|
|
109
|
+
MODEL=gpt-4o
|
|
110
|
+
LANGUAGE=en
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Example configuration for Groq
|
|
114
|
+
|
|
115
|
+
```dotenv
|
|
116
|
+
PROVIDER=groq
|
|
117
|
+
API_KEY=your_groq_api_key
|
|
118
|
+
MODEL=mixtral-8x7b-32768
|
|
119
|
+
LANGUAGE=en
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Example configuration for Anthropic
|
|
123
|
+
|
|
124
|
+
```dotenv
|
|
125
|
+
PROVIDER=anthropic
|
|
126
|
+
API_KEY=your_anthropic_api_key
|
|
127
|
+
MODEL=claude-3-5-sonnet-20241022
|
|
128
|
+
LANGUAGE=en
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## π Using Gitai
|
|
132
|
+
|
|
133
|
+
After installing and configuring Gitai, you can start using it to automatically generate commit messages for your project.
|
|
134
|
+
|
|
135
|
+
To use Gitai, open the terminal in your project's root directory. This is important because Gitai needs access to your project's files to analyze the changes and generate commit messages.
|
|
136
|
+
|
|
137
|
+
Once the terminal is open in your project's root, you can run Gitai with the following command:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
gitai <project_path> '<generic_message>'
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Replace `<project_path>` with the path to your project's directory and `<generic_message>` with a basic description of the change you made in the project.
|
|
144
|
+
|
|
145
|
+
For example, if you have the terminal open in your project's root and the change was to add a new feature, you can simply type:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
gitai . 'Added new feature'
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
If you wish to analyze only a specific folder or a project in another directory, for example, if you made a change in your project located at `/Users/username/MyProject`, you can run Gitai with the following command:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
gitai /Users/username/MyProject 'Added new feature'
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
To automatically generate the commit and push it, you can add the `--push` flag to the command:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
gitai . 'Added new feature' --push
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## π Generating Release Notes
|
|
164
|
+
|
|
165
|
+
Gitai includes a built-in release notes generator that analyzes commits since the last tag and creates detailed release documentation.
|
|
166
|
+
|
|
167
|
+
To generate release notes:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
npm run release-notes -- <old-tag> <new-version>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Example:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
npm run release-notes -- v0.0.1 v0.0.2
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## π¨βπ» Development
|
|
180
|
+
|
|
181
|
+
### Prerequisites
|
|
182
|
+
|
|
183
|
+
- Node.js 18 or higher
|
|
184
|
+
- npm (Node package manager)
|
|
185
|
+
- git
|
|
186
|
+
|
|
187
|
+
### Environment Setup
|
|
188
|
+
|
|
189
|
+
1. Clone the repository to your local machine using `git clone`.
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
git clone https://github.com/leandrosilvaferreira/gitai-js
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
2. Navigate to the project directory.
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
cd gitai-js
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
3. Install the project dependencies.
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
npm install
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Building the Project
|
|
208
|
+
|
|
209
|
+
To build the project, run:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
npm run build
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
This will compile the TypeScript code and bundle it using TSUP.
|
|
216
|
+
|
|
217
|
+
### Testing Locally
|
|
218
|
+
|
|
219
|
+
You can test the CLI locally by linking it:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
npm link
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Then run `gitai` in any directory to test it.
|
|
226
|
+
|
|
227
|
+
## π Contributing
|
|
228
|
+
|
|
229
|
+
We appreciate your interest in contributing to Gitai! Here are some guidelines to help you through the process:
|
|
230
|
+
|
|
231
|
+
1. **Fork the Repository**: Fork the Gitai repository to your GitHub account. This means you will have a copy of the repository in your own account, allowing you to make changes without affecting the original project.
|
|
232
|
+
2. **Clone the Repository**: Clone the repository to your local machine so that you can make changes.
|
|
233
|
+
3. **Create a Branch**: Create a new branch in your fork for your changes. This helps separate your changes from others that may be happening simultaneously.
|
|
234
|
+
4. **Make Your Changes**: Make the changes that you believe will improve the project. This can be adding a new feature, fixing a bug, or improving the documentation.
|
|
235
|
+
5. **Test Your Changes**: Ensure that your changes do not break anything and that the code still works as expected.
|
|
236
|
+
6. **Submit a Pull Request**: Submit a pull request to the original repository proposing your changes. Make sure to provide a detailed description of your changes so that the project maintainers can understand what you did and why.
|
|
237
|
+
|
|
238
|
+
## π Code of Conduct
|
|
239
|
+
|
|
240
|
+
We ask that all contributors follow our code of conduct. Mutual respect is essential for a healthy collaborative environment. Please be professional and respectful to all contributors.
|
|
241
|
+
|
|
242
|
+
## π Support
|
|
243
|
+
|
|
244
|
+
If you have any questions or issues, please open an issue. We will do our best to help you.
|
|
245
|
+
|
|
246
|
+
## π¨ Contact
|
|
247
|
+
|
|
248
|
+
If you wish to contact the project maintainers, please send an email to: [leandro@notyped.com](mailto:leandro@notyped.com)
|
|
249
|
+
|
|
250
|
+
Thank you for your interest in our project. We look forward to your contributions!
|
|
251
|
+
|
|
252
|
+
## π€ Author
|
|
253
|
+
|
|
254
|
+
**Leandro Silva Ferreira**
|
|
255
|
+
|
|
256
|
+
- GitHub: [@leandrosilvaferreira](https://github.com/leandrosilvaferreira)
|
|
257
|
+
- Twitter: [@leandrosfer](https://twitter.com/leandrosfer)
|
|
258
|
+
- Email: [leandro@notyped.com](mailto:leandro@notyped.com)
|
|
259
|
+
- LinkedIn: [Leandro Ferreira](https://www.linkedin.com/in/leandrosilvaferreira/)
|
|
260
|
+
|
|
261
|
+
## π License
|
|
262
|
+
|
|
263
|
+
This project is licensed under the MIT License. This means you are free to copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software, provided that you give appropriate credit to the original author and reproduce the license in all copies or substantial portions of the software.
|
|
264
|
+
|
|
265
|
+
For more details, see the [LICENSE](LICENSE.md) file in the repository.
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
# π§π· PortuguΓͺs
|
|
270
|
+
|
|
271
|
+
# Gitai - Conventional Commits automatizados no Git com IA
|
|
272
|
+
|
|
273
|
+
[](https://github.com/leandrosilvaferreira/gitai-js/releases)
|
|
274
|
+
[](https://star-history.com/#leandrosilvaferreira/gitai-js)
|
|
275
|
+
[](https://github.com/leandrosilvaferreira/gitai-js/fork)
|
|
276
|
+
|
|
277
|
+
Gitai Γ© um projeto TypeScript/Node.js que serve como uma ferramenta de automaΓ§Γ£o para gerenciamento de commits no Git. Ele Γ© projetado para analisar projetos escritos em vΓ‘rias linguagens de programaΓ§Γ£o, incluindo Node.js, Python, Java, Go e PHP.
|
|
278
|
+
|
|
279
|
+
A aplicaΓ§Γ£o analisa as alteraΓ§Γ΅es feitas em um projeto, identifica a linguagem de programaΓ§Γ£o usada e, com base nisso, gera uma mensagem de commit detalhada seguindo o padrΓ£o Conventional Commits. Este padrΓ£o Γ© amplamente adotado para tornar as mensagens de commit mais descritivas e ΓΊteis.
|
|
280
|
+
|
|
281
|
+
AlΓ©m disso, Gitai automatiza o processo de commit, adicionando todas as alteraΓ§Γ΅es ao Γndice do Git, realizando o commit com a mensagem gerada e, opcionalmente, fazendo push das alteraΓ§Γ΅es para o repositΓ³rio remoto.
|
|
282
|
+
|
|
283
|
+
Para a geraΓ§Γ£o da mensagem de commit, Γ© possΓvel escolher entre os modelos de linguagem avanΓ§ados da `OpenAI`, `Groq` ou `Anthropic`.
|
|
284
|
+
|
|
285
|
+
## π₯ Tutorial em VΓdeo
|
|
286
|
+
|
|
287
|
+
Clique na imagem abaixo para assistir ao tutorial em vΓdeo sobre o Gitai:
|
|
288
|
+
|
|
289
|
+
[](https://www.youtube.com/watch?v=GAQ4mmGxg7c "AUTOMATIZAΓΓO DE COMMITS DO GIT COM IA: GITAI (OPEN SOURCE E GRATUITO)")
|
|
290
|
+
|
|
291
|
+
## β‘ Instalando a AplicaΓ§Γ£o
|
|
292
|
+
|
|
293
|
+
O Gitai pode ser instalado globalmente via npm, tornando-o disponΓvel em todos os seus projetos:
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
npm install -g gitai
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
ApΓ³s a instalaΓ§Γ£o, o comando `gitai` estarΓ‘ disponΓvel no seu terminal.
|
|
300
|
+
|
|
301
|
+
## π€ Escolhendo o Modelo de IA
|
|
302
|
+
|
|
303
|
+
O Gitai oferece suporte a trΓͺs provedores de IA para gerar mensagens de commit: `OpenAI`, `Groq` e `Anthropic`.
|
|
304
|
+
|
|
305
|
+
Cada um tem suas caracterΓsticas, custos e limites de utilizaΓ§Γ£o.
|
|
306
|
+
|
|
307
|
+
Todos os provedores sΓ£o altamente capazes, mas sua escolha pode depender de suas necessidades especΓficas e do orΓ§amento disponΓvel.
|
|
308
|
+
|
|
309
|
+
Se vocΓͺ precisa de uma grande capacidade de processamento e pode arcar com os custos, OpenAI Γ© uma excelente opΓ§Γ£o. Se vocΓͺ prefere um serviΓ§o sem custo e pode gerenciar dentro dos limites de utilizaΓ§Γ£o, Groq Γ© uma alternativa viΓ‘vel. Para raciocΓnio avanΓ§ado e grandes janelas de contexto, Anthropic Claude oferece capacidades de ponta.
|
|
310
|
+
|
|
311
|
+
Abaixo estΓ£o as informaΓ§Γ΅es detalhadas sobre cada provedor para ajudΓ‘-lo a escolher o melhor para suas necessidades.
|
|
312
|
+
|
|
313
|
+
### OpenAI
|
|
314
|
+
|
|
315
|
+
OpenAI Γ© um serviΓ§o pago que oferece modelos de linguagem avanΓ§ados.
|
|
316
|
+
|
|
317
|
+
O modelo mais eficiente disponΓvel Γ© o `gpt-4o`, que tem uma janela de contexto de 128K tokens.
|
|
318
|
+
|
|
319
|
+
- **Custo**:
|
|
320
|
+
- $2.50 por 1M tokens para Input
|
|
321
|
+
- $10.00 por 1M tokens para Output
|
|
322
|
+
- **Site**: [OpenAI](https://platform.openai.com/docs/introduction)
|
|
323
|
+
|
|
324
|
+
### Groq
|
|
325
|
+
|
|
326
|
+
Groq Γ© um serviΓ§o gratuito, mas com limites de utilizaΓ§Γ£o.
|
|
327
|
+
|
|
328
|
+
O modelo recomendado Γ© o `mixtral-8x7b-32768`, que oferece uma janela de contexto de 32,768 tokens.
|
|
329
|
+
|
|
330
|
+
- **Limites de UtilizaΓ§Γ£o**:
|
|
331
|
+
- **Requests por Minuto**: 30
|
|
332
|
+
- **Requests por Dia**: 14,400
|
|
333
|
+
- **Tokens por Minuto**: 5,000
|
|
334
|
+
- **Site**: [Groq](https://console.groq.com/)
|
|
335
|
+
|
|
336
|
+
### Anthropic
|
|
337
|
+
|
|
338
|
+
Anthropic Γ© um serviΓ§o pago que oferece modelos de IA avanΓ§ados com excelentes capacidades de raciocΓnio.
|
|
339
|
+
|
|
340
|
+
O modelo recomendado Γ© o `claude-3-5-sonnet-20241022`, que tem uma janela de contexto de 200K tokens.
|
|
341
|
+
|
|
342
|
+
- **Custo**:
|
|
343
|
+
- $3.00 por 1M tokens para Input
|
|
344
|
+
- $15.00 por 1M tokens para Output
|
|
345
|
+
- **CaracterΓsticas**: RaciocΓnio avanΓ§ado, grande janela de contexto, excelente compreensΓ£o de cΓ³digo
|
|
346
|
+
- **Site**: [Anthropic](https://console.anthropic.com/)
|
|
347
|
+
|
|
348
|
+
## π± ConfiguraΓ§Γ£o Inicial
|
|
349
|
+
|
|
350
|
+
Na primeira vez que vocΓͺ executar o `gitai`, um **Assistente de ConfiguraΓ§Γ£o** amigΓ‘vel serΓ‘ iniciado automaticamente para ajudΓ‘-lo a configurar seu provedor de IA preferido, chave de API, modelo e idioma.
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
gitai
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
O assistente irΓ‘ guiΓ‘-lo atravΓ©s de:
|
|
357
|
+
|
|
358
|
+
1. **SeleΓ§Γ£o de Idioma**: Escolha seu idioma preferido (InglΓͺs, PortuguΓͺs, Espanhol, etc.)
|
|
359
|
+
2. **SeleΓ§Γ£o de Provedor**: Escolha entre OpenAI, Groq ou Anthropic
|
|
360
|
+
3. **Chave de API**: Insira sua chave de API para o provedor selecionado
|
|
361
|
+
4. **SeleΓ§Γ£o de Modelo**: Escolha o modelo de IA a ser usado (ex: `gpt-4o`, `mixtral-8x7b-32768`, `claude-3-5-sonnet-20241022`)
|
|
362
|
+
|
|
363
|
+
Sua configuraΓ§Γ£o Γ© salva globalmente em `~/.gitai`, entΓ£o vocΓͺ nΓ£o precisa configurΓ‘-la para cada projeto.
|
|
364
|
+
|
|
365
|
+
### Exemplo de configuraΓ§Γ£o para OpenAI
|
|
366
|
+
|
|
367
|
+
```dotenv
|
|
368
|
+
PROVIDER=openai
|
|
369
|
+
API_KEY=your_openai_api_key
|
|
370
|
+
MODEL=gpt-4o
|
|
371
|
+
LANGUAGE=en
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Exemplo de configuraΓ§Γ£o para Groq
|
|
375
|
+
|
|
376
|
+
```dotenv
|
|
377
|
+
PROVIDER=groq
|
|
378
|
+
API_KEY=your_groq_api_key
|
|
379
|
+
MODEL=mixtral-8x7b-32768
|
|
380
|
+
LANGUAGE=en
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Exemplo de configuraΓ§Γ£o para Anthropic
|
|
384
|
+
|
|
385
|
+
```dotenv
|
|
386
|
+
PROVIDER=anthropic
|
|
387
|
+
API_KEY=your_anthropic_api_key
|
|
388
|
+
MODEL=claude-3-5-sonnet-20241022
|
|
389
|
+
LANGUAGE=en
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## π Usando o Gitai
|
|
393
|
+
|
|
394
|
+
Depois de instalar e configurar o Gitai, vocΓͺ pode comeΓ§ar a usΓ‘-lo para gerar mensagens de commit automaticamente para o seu projeto.
|
|
395
|
+
|
|
396
|
+
Para usar o Gitai, vocΓͺ precisa abrir o terminal na raiz do seu projeto. Isso Γ© importante porque o Gitai precisa ter acesso aos arquivos do seu projeto para analisar as alteraΓ§Γ΅es e gerar as mensagens de commit.
|
|
397
|
+
|
|
398
|
+
Uma vez que o terminal esteja aberto na raiz do seu projeto, vocΓͺ pode executar o Gitai com o seguinte comando:
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
gitai <caminho_do_projeto> '<mensagem_genΓ©rica>'
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
Substitua `<caminho_do_projeto>` pelo caminho do diretΓ³rio do seu projeto e `<mensagem_genΓ©rica>` por uma descriΓ§Γ£o bΓ‘sica da mudanΓ§a que vocΓͺ fez no projeto.
|
|
405
|
+
|
|
406
|
+
Se vocΓͺ estiver com o terminal aberto na raiz do seu projeto e a mudanΓ§a foi para adicionar uma nova funcionalidade, vocΓͺ pode simplesmente digitar:
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
gitai . 'Adicionada nova funcionalidade'
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Se vocΓͺ deseja analisar somente uma pasta especΓfica ou um projeto em outra pasta, por exemplo, se vocΓͺ fez uma alteraΓ§Γ£o no seu projeto localizado em `/Users/username/MeuProjeto`, vocΓͺ pode executar o Gitai com o seguinte comando:
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
gitai /Users/username/MeuProjeto 'Adicionada nova funcionalidade'
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
Para gerar o commit e fazer push de forma automΓ‘tica, vocΓͺ pode adicionar a flag `--push` ao comando:
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
gitai . 'Adicionada nova funcionalidade' --push
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## π Gerando Notas de LanΓ§amento (Release Notes)
|
|
425
|
+
|
|
426
|
+
O Gitai inclui um gerador de notas de lanΓ§amento integrado que analisa os commits desde a ΓΊltima tag e cria documentaΓ§Γ£o de lanΓ§amento detalhada.
|
|
427
|
+
|
|
428
|
+
Para gerar notas de lanΓ§amento:
|
|
429
|
+
|
|
430
|
+
```bash
|
|
431
|
+
npm run release-notes -- <tag-antiga> <nova-versΓ£o>
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
Exemplo:
|
|
435
|
+
|
|
436
|
+
```bash
|
|
437
|
+
npm run release-notes -- v0.0.1 v0.0.2
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
## π¨βπ» Desenvolvimento
|
|
441
|
+
|
|
442
|
+
### PrΓ©-requisitos
|
|
443
|
+
|
|
444
|
+
- Node.js 18 ou superior
|
|
445
|
+
- npm (gerenciador de pacotes do Node)
|
|
446
|
+
- git
|
|
447
|
+
|
|
448
|
+
### ConfiguraΓ§Γ£o do Ambiente
|
|
449
|
+
|
|
450
|
+
1. Clone o repositΓ³rio para a sua mΓ‘quina local usando `git clone`.
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
git clone https://github.com/leandrosilvaferreira/gitai-js
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
2. Navegue atΓ© o diretΓ³rio do projeto.
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
cd gitai-js
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
3. Instale as dependΓͺncias do projeto.
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
npm install
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Compilando o Projeto
|
|
469
|
+
|
|
470
|
+
Para compilar o projeto, execute:
|
|
471
|
+
|
|
472
|
+
```bash
|
|
473
|
+
npm run build
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
Isso irΓ‘ compilar o cΓ³digo TypeScript e empacotΓ‘-lo usando TSUP.
|
|
477
|
+
|
|
478
|
+
### Testando Localmente
|
|
479
|
+
|
|
480
|
+
VocΓͺ pode testar a CLI localmente fazendo um link:
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
npm link
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
Depois execute `gitai` em qualquer diretΓ³rio para testΓ‘-lo.
|
|
487
|
+
|
|
488
|
+
## π Contribuindo
|
|
489
|
+
|
|
490
|
+
Agradecemos o seu interesse em contribuir para o Gitai! Aqui estΓ£o algumas diretrizes que podem ajudΓ‘-lo no processo:
|
|
491
|
+
|
|
492
|
+
1. **Fork o RepositΓ³rio**: FaΓ§a um fork do repositΓ³rio Gitai para a sua conta do GitHub. Isso significa que vocΓͺ terΓ‘ uma cΓ³pia do repositΓ³rio em sua prΓ³pria conta, permitindo que vocΓͺ faΓ§a alteraΓ§Γ΅es sem afetar o projeto original.
|
|
493
|
+
|
|
494
|
+
2. **Clone o RepositΓ³rio**: Clone o repositΓ³rio para a sua mΓ‘quina local para que vocΓͺ possa fazer alteraΓ§Γ΅es.
|
|
495
|
+
|
|
496
|
+
3. **Crie uma Branch**: Crie uma nova branch em seu fork para fazer suas alteraΓ§Γ΅es. Isso ajuda a separar suas alteraΓ§Γ΅es de outras que possam estar acontecendo simultaneamente.
|
|
497
|
+
|
|
498
|
+
4. **FaΓ§a suas AlteraΓ§Γ΅es**: FaΓ§a as alteraΓ§Γ΅es que vocΓͺ acha que melhorariam o projeto. Isso pode ser a adiΓ§Γ£o de uma nova funcionalidade, a correΓ§Γ£o de um bug ou a melhoria da documentaΓ§Γ£o.
|
|
499
|
+
|
|
500
|
+
5. **Teste suas AlteraΓ§Γ΅es**: Certifique-se de que suas alteraΓ§Γ΅es nΓ£o quebram nada e que o cΓ³digo ainda funciona como esperado.
|
|
501
|
+
|
|
502
|
+
6. **Envie um Pull Request**: Envie um pull request para o repositΓ³rio original propondo suas alteraΓ§Γ΅es. Certifique-se de dar uma descriΓ§Γ£o detalhada de suas alteraΓ§Γ΅es para que os mantenedores do projeto possam entender o que vocΓͺ fez e por quΓͺ.
|
|
503
|
+
|
|
504
|
+
## π CΓ³digo de Conduta
|
|
505
|
+
|
|
506
|
+
Pedimos que todos os contribuintes sigam nosso cΓ³digo de conduta. Respeito mΓΊtuo Γ© fundamental para um ambiente de colaboraΓ§Γ£o saudΓ‘vel. Por favor, seja profissional e respeitoso com os outros contribuintes.
|
|
507
|
+
|
|
508
|
+
## π Suporte
|
|
509
|
+
|
|
510
|
+
Se vocΓͺ tiver alguma dΓΊvida ou problema, por favor, abra uma issue. Faremos o nosso melhor para ajudΓ‘-lo.
|
|
511
|
+
|
|
512
|
+
## π¨ Contato
|
|
513
|
+
|
|
514
|
+
Se vocΓͺ quiser entrar em contato com os mantenedores do projeto, por favor, envie um e-mail para: [leandro@notyped.com](mailto:leandro@notyped.com)
|
|
515
|
+
|
|
516
|
+
Obrigado por seu interesse em nosso projeto. Estamos ansiosos para ver suas contribuiΓ§Γ΅es!
|
|
517
|
+
|
|
518
|
+
## π€ Autor
|
|
519
|
+
|
|
520
|
+
**Leandro Silva Ferreira**
|
|
521
|
+
|
|
522
|
+
- GitHub: [@leandrosilvaferreira](https://github.com/leandrosilvaferreira)
|
|
523
|
+
- Twitter: [@leandrosfer](https://twitter.com/leandrosfer)
|
|
524
|
+
- Email: [leandro@notyped.com](mailto:leandro@notyped.com)
|
|
525
|
+
- LinkedIn: [Leandro Ferreira](https://www.linkedin.com/in/leandrosilvaferreira/)
|
|
526
|
+
|
|
527
|
+
## π LicenΓ§a
|
|
528
|
+
|
|
529
|
+
Este projeto estΓ‘ licenciado sob a LicenΓ§a MIT. Isso significa que vocΓͺ Γ© livre para copiar, modificar, mesclar, publicar, distribuir, sublicenciar e/ou vender cΓ³pias do software, desde que vocΓͺ dΓͺ o crΓ©dito apropriado ao autor original e reproduza a licenΓ§a em todas as cΓ³pias ou partes substanciais do software.
|
|
530
|
+
|
|
531
|
+
Para mais detalhes, consulte o arquivo [LICENSE](LICENSE.md) no repositΓ³rio.
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import h from"chalk";import{Command as ee}from"commander";import te from"path";import D from"@anthropic-ai/sdk";import S from"groq-sdk";import F from"openai";import c from"chalk";var s={header:e=>{console.log(c.cyan.bold(`\u{1F680} ${e}`))},success:e=>{console.log(c.green.bold(`\u2705 ${e}`))},info:e=>{console.log(c.blue.bold(`\u2139\uFE0F ${e}`))},warning:e=>{console.log(c.yellow.bold(`\u26A0\uFE0F ${e}`))},error:e=>{console.log(c.red.bold(`\u274C ${e}`))},git:e=>{console.log(c.magenta.bold(`\u{1F504} ${e}`))},ai:e=>{console.log(c.cyan.bold(`\u{1F916} ${e}`))},commit:e=>{console.log(`
|
|
3
|
+
`+c.bgBlue.white.bold(" Generated commit message: ")+`
|
|
4
|
+
`),console.log(c.white.bold(e)),console.log()}};var w=class{config;openai;groq;anthropic;constructor(o){this.config=o,this.initializeClient()}initializeClient(){switch(this.config.provider){case"openai":this.openai=new F({apiKey:this.config.apiKey});break;case"groq":this.groq=new S({apiKey:this.config.apiKey});break;case"anthropic":this.anthropic=new D({apiKey:this.config.apiKey});break;default:s.error(`Provider ${this.config.provider} is not supported.`),process.exit(1)}}getCommitSystemPrompt(){return`
|
|
5
|
+
You are an assistant that helps generate commit messages for a Git repository.
|
|
6
|
+
Commit messages must follow the Conventional Commits standard, which uses ONLY these specific prefixes to categorize the type of change made: feat, fix, docs, chore.
|
|
7
|
+
The description must be concise and clear, explaining what was done, the reason for the change, and, if applicable, the impact of the change.
|
|
8
|
+
The messages must be generated based on the changes provided by the 'git diff' command and an optional basic description provided by the user.
|
|
9
|
+
|
|
10
|
+
Mandatory rules:
|
|
11
|
+
- DO NOT add any comments or additional explanations beyond the generated commit message.
|
|
12
|
+
- DO NOT use symbols such as \`\`\` or any other formatting to denote the commit message.
|
|
13
|
+
- DO NOT add line breaks or whitespace before the commit message.
|
|
14
|
+
- The output must be ONLY the final commit message as per the instructions.
|
|
15
|
+
- The first line of the message must start with one of these EXACT prefixes: feat, fix, docs, chore.
|
|
16
|
+
- After the first line, always add an objective explanation of the changes made, the reason for the change, and, if applicable, the impact of the change.
|
|
17
|
+
|
|
18
|
+
<output_format>
|
|
19
|
+
CRITICAL: Your response must follow this exact structure:
|
|
20
|
+
|
|
21
|
+
Line 1: [prefix]: [concise description]
|
|
22
|
+
(where prefix must be exactly one of: feat, fix, docs, chore)
|
|
23
|
+
Line 2: [EMPTY LINE - mandatory line break]
|
|
24
|
+
Line 3+: [detailed explanation]
|
|
25
|
+
|
|
26
|
+
CORRECT format example:
|
|
27
|
+
feat: add user authentication system
|
|
28
|
+
|
|
29
|
+
Implement JWT-based authentication with login and registration endpoints. Add middleware for route protection and user session management. This enhancement improves application security and enables personalized user experiences.
|
|
30
|
+
|
|
31
|
+
INCORRECT format (everything in one line):
|
|
32
|
+
feat: add user authentication system - Implement JWT-based authentication with login and registration endpoints...
|
|
33
|
+
</output_format>
|
|
34
|
+
|
|
35
|
+
If the instructions are not followed correctly, the result will not be accepted.
|
|
36
|
+
`.trim()}getCommitUserPrompt(o,i,t){return`
|
|
37
|
+
Based on the information provided below, create a commit message following the Conventional Commits standard.
|
|
38
|
+
|
|
39
|
+
The ONLY accepted prefixes for this project are:
|
|
40
|
+
- feat: A new feature
|
|
41
|
+
- fix: A bug fix
|
|
42
|
+
- docs: Documentation changes
|
|
43
|
+
- chore: Maintenance changes or minor fixes that do not alter functionality
|
|
44
|
+
|
|
45
|
+
For your information and better understanding, the project in question uses the programming language ${i}.
|
|
46
|
+
|
|
47
|
+
Basic change description provided by the developer, which you should use as the basis for your message: '${t}'
|
|
48
|
+
|
|
49
|
+
Below are the detailed changes (including modified files and what was added, changed, or removed) generated by the 'git diff' command:
|
|
50
|
+
|
|
51
|
+
\`\`\`
|
|
52
|
+
${o}
|
|
53
|
+
\`\`\`
|
|
54
|
+
|
|
55
|
+
Based on the above information, improve the basic description to create an objective commit message.
|
|
56
|
+
Mandatory rules:
|
|
57
|
+
- You must follow the Conventional Commits standard.
|
|
58
|
+
- The first line of the message must start with one of these EXACT prefixes (feat, fix, docs, chore) followed by a concise description explaining what was done.
|
|
59
|
+
- After the first line, always add an objective explanation of the changes made, the reason for the change, and, if applicable, the impact of the change.
|
|
60
|
+
- Whenever possible, mention only the main modified files in the commit message without including the path.
|
|
61
|
+
- DO NOT add any comments or additional explanations beyond the generated commit message.
|
|
62
|
+
- DO NOT use symbols such as \`\`\` or any other formatting to denote the commit message.
|
|
63
|
+
- DO NOT add line breaks or whitespace before the commit message.
|
|
64
|
+
- The output must be ONLY the final commit message as per the instructions.
|
|
65
|
+
- You must use the language '${this.config.language}' in your response generation.
|
|
66
|
+
|
|
67
|
+
<output_format>
|
|
68
|
+
Your response must follow this exact format:
|
|
69
|
+
|
|
70
|
+
Line 1: [prefix]: [concise description]
|
|
71
|
+
Line 2: [empty line]
|
|
72
|
+
Line 3+: [detailed explanation of changes, reasons, and impact]
|
|
73
|
+
</output_format>
|
|
74
|
+
`.trim()}async generateCommitMessage(o,i,t){let n=this.getCommitSystemPrompt(),r=this.getCommitUserPrompt(o,i,t);return await this.callApi(n,r)+`
|
|
75
|
+
|
|
76
|
+
\u{1F916} Commit generated with [GitaiJS](https://github.com/leandrosilvaferreira/gitai-js)`}async generateReleaseNotes(o,i,t){let n=`
|
|
77
|
+
You are an assistant that helps generate release notes for a Git repository.
|
|
78
|
+
Commit messages should be organized into categories such as New Features, Bug Fixes, and Other Changes.
|
|
79
|
+
The output must be a markdown-formatted text according to the provided template, with no additional comments or formatting.
|
|
80
|
+
`.trim(),r=`
|
|
81
|
+
You are an assistant that helps generate release notes for a Git repository.
|
|
82
|
+
Below are the commits since the last tag ${t}.
|
|
83
|
+
Please organize the commits into the following categories: New Features, Bug Fixes, and Other Changes.
|
|
84
|
+
Generate a release message in markdown format in the language '${this.config.language}' using the following template:
|
|
85
|
+
|
|
86
|
+
\`\`\`
|
|
87
|
+
# Release ${i}
|
|
88
|
+
<SUMMARY/>
|
|
89
|
+
|
|
90
|
+
### New Features
|
|
91
|
+
- Description of new features (commits).
|
|
92
|
+
|
|
93
|
+
### Bug Fixes
|
|
94
|
+
- Description of bug fixes (commits).
|
|
95
|
+
|
|
96
|
+
### Other Changes
|
|
97
|
+
- Description of other changes (commits).
|
|
98
|
+
|
|
99
|
+
We thank all the contributors who made this release possible! For more details, please refer to the complete version notes.
|
|
100
|
+
|
|
101
|
+
**Full Changelog:** [See commits for v${i}](https://github.com/leandrosilvaferreira/gitai-js/compare/${t}...v${i})
|
|
102
|
+
\`\`\`
|
|
103
|
+
|
|
104
|
+
Commits:
|
|
105
|
+
${o}
|
|
106
|
+
|
|
107
|
+
Important rules:
|
|
108
|
+
- The generated content must be in the language '${this.config.language}'.
|
|
109
|
+
- Replace <SUMMARY/> in the template with a brief and enthusiastic summary of the changes made since the last tag ${t}.
|
|
110
|
+
- DO NOT add any additional comments or explanations.
|
|
111
|
+
- DO NOT use symbols like \`\`\` to denote commit messages.
|
|
112
|
+
- The message must be clear, concise, and well-organized.
|
|
113
|
+
- Remember to follow the provided template.
|
|
114
|
+
|
|
115
|
+
If the instructions are not followed correctly, the result will not be accepted.
|
|
116
|
+
`.trim();return this.callApi(n,r)}async callApi(o,i){if(this.config.provider==="openai"&&this.openai){s.ai(`Provider: openai - Model: ${this.config.model}`);let n=["o1","o3","gpt-5"].some(v=>this.config.model.startsWith(v))?"max_completion_tokens":"max_tokens";return(await this.openai.chat.completions.create({messages:[{role:"system",content:o},{role:"user",content:i}],model:this.config.model,temperature:.5,top_p:1,frequency_penalty:0,presence_penalty:0,[n]:500})).choices[0].message.content?.trim()||""}else{if(this.config.provider==="groq"&&this.groq)return s.ai(`Provider: groq - Model: ${this.config.model}`),(await this.groq.chat.completions.create({messages:[{role:"system",content:o},{role:"user",content:i}],model:this.config.model,temperature:.5,max_tokens:500,top_p:1,frequency_penalty:0,presence_penalty:0})).choices[0].message.content?.trim()||"";if(this.config.provider==="anthropic"&&this.anthropic){s.ai(`Provider: anthropic - Model: ${this.config.model}`);let n=(await this.anthropic.messages.create({model:this.config.model,max_tokens:500,temperature:.5,system:o,messages:[{role:"user",content:i}]})).content[0];return n.type==="text"?n.text.trim():""}}return""}};import C from"fs";import _ from"os";import Y from"path";import q from"semver";var d="0.0.11",j="gitai",b={node:">=18"};var u=Y.join(_.homedir(),".gitai"),P=()=>{try{return C.existsSync(u)}catch{return!1}},E=()=>{if(!P())throw new Error(`Configuration file not found at ${u}`);let e=C.readFileSync(u,"utf-8"),o={};return e.split(`
|
|
117
|
+
`).forEach(i=>{let[t,...n]=i.split("=");if(t&&n&&t.trim()){let r=n.join("=").trim();r.startsWith('"')&&r.endsWith('"')&&(r=r.slice(1,-1)),r.startsWith("'")&&r.endsWith("'")&&(r=r.slice(1,-1)),o[t.trim()]=r}}),o},$=e=>{let o=Object.entries(e).map(([i,t])=>`${i}=${t}`).join(`
|
|
118
|
+
`);C.writeFileSync(u,o,{mode:384})},R=()=>{let e=b.node;return q.satisfies(process.version,e)};import{execa as K}from"execa";import N from"fs/promises";import U from"os";import B from"path";async function l(e,o=process.cwd(),i=!0){try{let t=await K("git",e,{cwd:o,reject:!1});return t.exitCode!==0&&i&&(s.error(`Error executing command: git ${e.join(" ")}`),s.error(`Standard output: ${t.stdout}`),s.error(`Error output: ${t.stderr}`),process.exit(1)),{stdout:t.stdout.trim(),stderr:t.stderr.trim(),exitCode:t.exitCode??1}}catch(t){if(i){let r=t instanceof Error?t.message:String(t);s.error(`Unexpected error executing git command: ${r}`),process.exit(1)}return{stdout:"",stderr:t instanceof Error?t.message:String(t),exitCode:1}}}async function A(e){let{stdout:o}=await l(["status","--porcelain"],e);return o.length>0}async function T(e){let{stdout:o}=await l(["status","-uno"],e);return o.includes("Your branch is ahead")||o.includes("Seu branch est\xE1 \xE0 frente")}async function L(e){let{stdout:o,stderr:i,exitCode:t}=await l(["pull"],e,!1);if(t!==0){if(o.includes("CONFLICT")||o.includes("CONFLITO")||i.includes("CONFLICT")||i.includes("CONFLITO"))return s.warning("Conflitos detectados durante git pull:"),s.error(o||i),!1;s.error(`Error executing git pull: ${o||i}`),process.exit(1)}return s.success("Git pull executed successfully."),!0}async function O(e,o){await l(["add","."],o);let i=U.tmpdir(),t=B.join(i,`gitai_commit_${Date.now()}.txt`);try{await N.writeFile(t,e,"utf-8"),await l(["commit","-F",t],o)}finally{try{await N.unlink(t)}catch{}}}import W from"fs/promises";import z from"path";var J={"Node.js":["package.json","yarn.lock","package-lock.json","npm-shrinkwrap.json"],Python:["requirements.txt","Pipfile","pyproject.toml","setup.py","setup.cfg","manage.py"],Java:["pom.xml","build.gradle","build.gradle.kts","build.xml",".java-version"],Go:["go.mod","Gopkg.lock"],PHP:["composer.json","composer.lock","index.php"],Ruby:["Gemfile","Gemfile.lock","Rakefile","config.ru",".ruby-version"],Rust:["Cargo.toml","Cargo.lock"],Haskell:["stack.yaml","cabal.project"],Swift:["Package.swift"],Elixir:["mix.exs"],Dart:["pubspec.yaml"],Scala:["build.sbt"],Perl:["Makefile.PL","Build.PL"],R:[".Rproj"]},V={"C#":[".csproj",".sln"],Haskell:[".cabal"],Swift:[".xcodeproj",".xcworkspace"],Kotlin:[".kt",".kts"],"C/C++":[".c",".cpp",".h",".hpp"],JavaScript:[".js",".jsx"],TypeScript:[".ts",".tsx"],Python:[".py"],Java:[".java"]},H={"Node.js":"\u{1F7E2}",Python:"\u{1F40D}",Java:"\u2615",Go:"\u{1F439}",PHP:"\u{1F418}",Ruby:"\u{1F48E}",Rust:"\u{1F980}",Haskell:"\u{1F3A9}",Swift:"\u{1F34E}",Elixir:"\u{1F4A7}",Dart:"\u{1F3AF}",Scala:"\u2696\uFE0F",Perl:"\u{1F42A}",R:"\u{1F4CA}","C#":"\u{1F537}","C/C++":"\u2699\uFE0F",JavaScript:"\u{1F7E8}",TypeScript:"\u{1F537}",Unknown:"\u2753"};function X(e){return H[e]||"\u2753"}function k(e){let o=X(e);s.info(`${o} Linguagem detectada: ${e}
|
|
119
|
+
`)}async function I(e){try{let o=await W.readdir(e);for(let[i,t]of Object.entries(J))for(let n of t)if(!n.includes(z.sep)){if(o.includes(n))return i}for(let[i,t]of Object.entries(V))for(let n of o)if(t.some(r=>n.endsWith(r)))return i;return"Unknown"}catch{return"Unknown"}}import m from"chalk";import{execa as Q}from"execa";import Z from"inquirer";async function M(){console.clear(),console.log(m.bold.blue(`
|
|
120
|
+
\u{1F680} Welcome to GitAI v${d} Setup! \u{1F680}`)),console.log(m.dim(`Let's get you ready to code with AI assistance.
|
|
121
|
+
`));try{await Q("git",["--version"]),console.log(m.green("\u2705 Git is installed!"))}catch{console.log(m.red("\u274C Git is NOT installed or not accessible from PATH.")),console.log(m.yellow("Please install Git before proceeding.")),process.exit(1)}console.log(m.cyan(`
|
|
122
|
+
\u2699\uFE0F Global Configuration (saved to `+u+`)
|
|
123
|
+
`));let e=await Z.prompt([{type:"list",name:"LANGUAGE",message:"What language should the AI use for commit messages?",choices:[{name:"English",value:"en"},{name:"Portuguese (Brasil)",value:"pt-br"},{name:"Spanish",value:"es"},{name:"French",value:"fr"},{name:"German",value:"de"},{name:"Italian",value:"it"},{name:"Chinese",value:"zh"},{name:"Japanese",value:"ja"},{name:"Korean",value:"ko"}],default:"en"},{type:"list",name:"PROVIDER",message:"Which AI Provider do you want to use?",choices:[{name:"OpenAI",value:"openai"},{name:"Anthropic",value:"anthropic"},{name:"Groq",value:"groq"}],default:"openai"},{type:"password",name:"API_KEY",message:"Enter your API Key:",mask:"*",validate:i=>i.length>0?!0:"API Key is required"},{type:"input",name:"MODEL",message:"Model ID (e.g., gpt-4o, claude-3-5-sonnet):",default:i=>i.PROVIDER==="openai"?"gpt-4o":i.PROVIDER==="anthropic"?"claude-3-5-sonnet-20240620":i.PROVIDER==="groq"?"llama3-70b-8192":"gpt-4o"}]),o={LANGUAGE:e.LANGUAGE,PROVIDER:e.PROVIDER,API_KEY:e.API_KEY,MODEL:e.MODEL};return $(o),console.log(m.green(`
|
|
124
|
+
\u2728 Configuration saved successfully! \u2728`)),console.log(m.dim(`You are all set. Running GitAI...
|
|
125
|
+
`)),o}R()||(console.error(h.red(`
|
|
126
|
+
\u274C GitAI requires Node.js ${b.node} or higher.`)),console.error(h.yellow(` Current version: ${process.version}
|
|
127
|
+
`)),process.exit(1));var x=new ee;x.name(j).description("AI-powered git commit assistant").version(d);x.on("--help",()=>{console.log(""),console.log(h.cyan("\u2501".repeat(50))),console.log(h.bold.blue(` GitAI v${d}`)),console.log(h.dim(" AI-powered git commit assistant")),console.log(h.cyan("\u2501".repeat(50))),console.log("")});x.argument("[projectPath]","The path to the project",".").argument("[baseMessage]","The base commit message").option("-p, --push","Whether to push after committing",!1).action(async(e,o,i)=>{let t;try{P()?t=E():t=await M()}catch(a){let f=a instanceof Error?a.message:String(a);s.error(`Failed to load configuration: ${f}`),process.exit(1)}s.header(`Gitai v${d}`);let n=te.resolve(e);s.info(`\u{1F4C1} project_path: ${n}
|
|
128
|
+
`);let r=new w({provider:t.PROVIDER,model:t.MODEL,apiKey:t.API_KEY,language:t.LANGUAGE});try{process.chdir(n)}catch{s.error(`Failed to change directory to ${n}`),process.exit(1)}if(await A(n)){s.warning("Uncommitted local changes detected.");let a=await I(n);k(a);let{stdout:f}=await l(["diff"],n),y=o||"",G=await r.generateCommitMessage(f,a,y);s.commit(G),await O(G,n),s.success("Gitai successfully committed local changes.")}else s.info("No local changes to commit before git pull.");if(await L(n)||(s.error("Git pull failed due to conflicts. Please resolve the conflicts manually."),process.exit(1)),await A(n)){s.warning("Conflicts or uncommitted changes detected after pull.");let a=await I(n);k(a);let{stdout:f}=await l(["diff"],n),y=await r.generateCommitMessage(f,a,"Resolving conflicts after git pull");s.commit(y),await O(y,n),s.success("Gitai successfully committed changes after pull.")}else s.info("No changes to commit after git pull.");i.push&&(await T(n)?(await l(["push"],n),s.success("Gitai successfully pushed changes.")):s.info("No changes to push. The local branch is synchronized with the remote."))});x.parse();
|
|
129
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/services/ai.ts","../src/utils/logger.ts","../src/utils/config.ts","../src/version.ts","../src/utils/git.ts","../src/utils/language.ts","../src/utils/setup.ts"],"sourcesContent":["#!/usr/bin/env node\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport path from 'path';\n\nimport { AIService } from './services/ai.js';\nimport { checkConfigExists, loadConfig, validateNodeVersion } from './utils/config.js';\nimport { commitChanges, hasUncommittedChanges, isBranchAhead, performGitPull, runGitCommand } from './utils/git.js';\nimport { detectProjectLanguage, printDetectedLanguage } from './utils/language.js';\nimport { logger } from './utils/logger.js';\nimport { runSetup } from './utils/setup.js';\n\nimport { engines, name, version } from './version.js';\n\n// 0. Validate Node Version\nif (!validateNodeVersion()) {\n console.error(chalk.red(`\\nβ GitAI requires Node.js ${engines.node} or higher.`));\n console.error(chalk.yellow(` Current version: ${process.version}\\n`));\n process.exit(1);\n}\n\nconst program = new Command();\n\nprogram\n .name(name)\n .description('AI-powered git commit assistant')\n .version(version);\n\n// Custom help handler to show version\nprogram.on('--help', () => {\n console.log('');\n console.log(chalk.cyan('β'.repeat(50)));\n console.log(chalk.bold.blue(` GitAI v${version}`));\n console.log(chalk.dim(' AI-powered git commit assistant'));\n console.log(chalk.cyan('β'.repeat(50)));\n console.log('');\n});\n\nprogram\n .argument('[projectPath]', 'The path to the project', '.')\n .argument('[baseMessage]', 'The base commit message')\n .option('-p, --push', 'Whether to push after committing', false)\n .action(async (projectPathArg, baseMessageArg, options) => {\n \n // 1. Configuration Check (Global Only)\n let config;\n try {\n if (!checkConfigExists()) {\n config = await runSetup();\n } else {\n config = loadConfig();\n }\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to load configuration: ${errorMessage}`);\n process.exit(1);\n }\n\n logger.header(`Gitai v${version}`);\n \n const projectPath = path.resolve(projectPathArg);\n logger.info(`π project_path: ${projectPath}\\n`);\n\n const aiService = new AIService({\n provider: config.PROVIDER,\n model: config.MODEL,\n apiKey: config.API_KEY,\n language: config.LANGUAGE\n });\n\n // Change process CWD to project path to ensure git commands run there\n try {\n process.chdir(projectPath);\n } catch {\n logger.error(`Failed to change directory to ${projectPath}`);\n process.exit(1);\n }\n\n // 2. Check for uncommitted changes\n if (await hasUncommittedChanges(projectPath)) {\n logger.warning('Uncommitted local changes detected.');\n \n const projectLanguage = await detectProjectLanguage(projectPath);\n printDetectedLanguage(projectLanguage);\n \n const { stdout: diffOutput } = await runGitCommand(['diff'], projectPath);\n \n // Generate commit message\n // Allow empty base message (will rely on git diffs)\n const baseMessage = baseMessageArg || '';\n\n const commitMessage = await aiService.generateCommitMessage(diffOutput, projectLanguage, baseMessage);\n \n logger.commit(commitMessage);\n \n await commitChanges(commitMessage, projectPath);\n logger.success('Gitai successfully committed local changes.');\n \n } else {\n logger.info('No local changes to commit before git pull.');\n }\n\n // 3. Perform Git Pull\n const pullSuccessful = await performGitPull(projectPath);\n \n if (!pullSuccessful) {\n logger.error('Git pull failed due to conflicts. Please resolve the conflicts manually.');\n process.exit(1);\n }\n\n // 4. Check for conflicts/changes after pull\n if (await hasUncommittedChanges(projectPath)) {\n logger.warning('Conflicts or uncommitted changes detected after pull.');\n \n const projectLanguage = await detectProjectLanguage(projectPath);\n printDetectedLanguage(projectLanguage);\n \n const { stdout: diffOutput } = await runGitCommand(['diff'], projectPath);\n \n const commitMessage = await aiService.generateCommitMessage(diffOutput, projectLanguage, \"Resolving conflicts after git pull\");\n logger.commit(commitMessage);\n \n await commitChanges(commitMessage, projectPath);\n logger.success('Gitai successfully committed changes after pull.');\n\n } else {\n logger.info('No changes to commit after git pull.');\n }\n\n // 5. Push if requested\n if (options.push) {\n if (await isBranchAhead(projectPath)) {\n await runGitCommand(['push'], projectPath);\n logger.success('Gitai successfully pushed changes.');\n } else {\n logger.info('No changes to push. The local branch is synchronized with the remote.');\n }\n }\n\n });\n\nprogram.parse();\n","import Anthropic from '@anthropic-ai/sdk';\nimport Groq from 'groq-sdk';\nimport OpenAI from 'openai';\nimport { logger } from '../utils/logger.js';\n\ninterface AIConfig {\n provider: string;\n model: string;\n apiKey: string;\n language: string;\n}\n\nexport class AIService {\n private config: AIConfig;\n private openai?: OpenAI;\n private groq?: Groq;\n private anthropic?: Anthropic;\n\n constructor(config: AIConfig) {\n this.config = config;\n this.initializeClient();\n }\n\n private initializeClient() {\n switch (this.config.provider) {\n case 'openai':\n this.openai = new OpenAI({ apiKey: this.config.apiKey });\n break;\n case 'groq':\n this.groq = new Groq({ apiKey: this.config.apiKey });\n break;\n case 'anthropic':\n this.anthropic = new Anthropic({ apiKey: this.config.apiKey });\n break;\n default:\n logger.error(`Provider ${this.config.provider} is not supported.`);\n process.exit(1);\n }\n }\n\n private getCommitSystemPrompt(): string {\n return `\nYou are an assistant that helps generate commit messages for a Git repository.\nCommit messages must follow the Conventional Commits standard, which uses ONLY these specific prefixes to categorize the type of change made: feat, fix, docs, chore.\nThe description must be concise and clear, explaining what was done, the reason for the change, and, if applicable, the impact of the change.\nThe messages must be generated based on the changes provided by the 'git diff' command and an optional basic description provided by the user.\n\nMandatory rules:\n- DO NOT add any comments or additional explanations beyond the generated commit message.\n- DO NOT use symbols such as \\`\\`\\` or any other formatting to denote the commit message.\n- DO NOT add line breaks or whitespace before the commit message.\n- The output must be ONLY the final commit message as per the instructions.\n- The first line of the message must start with one of these EXACT prefixes: feat, fix, docs, chore.\n- After the first line, always add an objective explanation of the changes made, the reason for the change, and, if applicable, the impact of the change.\n\n<output_format>\nCRITICAL: Your response must follow this exact structure:\n\nLine 1: [prefix]: [concise description]\n(where prefix must be exactly one of: feat, fix, docs, chore)\nLine 2: [EMPTY LINE - mandatory line break]\nLine 3+: [detailed explanation]\n\nCORRECT format example:\nfeat: add user authentication system\n\nImplement JWT-based authentication with login and registration endpoints. Add middleware for route protection and user session management. This enhancement improves application security and enables personalized user experiences.\n\nINCORRECT format (everything in one line):\nfeat: add user authentication system - Implement JWT-based authentication with login and registration endpoints...\n</output_format>\n\nIf the instructions are not followed correctly, the result will not be accepted.\n`.trim();\n }\n\n private getCommitUserPrompt(diffOutput: string, projectLanguage: string, baseMessage: string): string {\n return `\nBased on the information provided below, create a commit message following the Conventional Commits standard.\n\nThe ONLY accepted prefixes for this project are:\n - feat: A new feature\n - fix: A bug fix\n - docs: Documentation changes\n - chore: Maintenance changes or minor fixes that do not alter functionality\n\nFor your information and better understanding, the project in question uses the programming language ${projectLanguage}.\n\nBasic change description provided by the developer, which you should use as the basis for your message: '${baseMessage}'\n\nBelow are the detailed changes (including modified files and what was added, changed, or removed) generated by the 'git diff' command:\n\n\\`\\`\\`\n${diffOutput}\n\\`\\`\\`\n\nBased on the above information, improve the basic description to create an objective commit message.\nMandatory rules:\n- You must follow the Conventional Commits standard.\n- The first line of the message must start with one of these EXACT prefixes (feat, fix, docs, chore) followed by a concise description explaining what was done.\n- After the first line, always add an objective explanation of the changes made, the reason for the change, and, if applicable, the impact of the change.\n- Whenever possible, mention only the main modified files in the commit message without including the path.\n- DO NOT add any comments or additional explanations beyond the generated commit message.\n- DO NOT use symbols such as \\`\\`\\` or any other formatting to denote the commit message.\n- DO NOT add line breaks or whitespace before the commit message.\n- The output must be ONLY the final commit message as per the instructions.\n- You must use the language '${this.config.language}' in your response generation.\n\n<output_format>\nYour response must follow this exact format:\n\nLine 1: [prefix]: [concise description]\nLine 2: [empty line]\nLine 3+: [detailed explanation of changes, reasons, and impact]\n</output_format>\n`.trim();\n }\n\n async generateCommitMessage(diffOutput: string, projectLanguage: string, baseMessage: string): Promise<string> {\n const systemPrompt = this.getCommitSystemPrompt();\n const userPrompt = this.getCommitUserPrompt(diffOutput, projectLanguage, baseMessage);\n \n const commitMessage = await this.callApi(systemPrompt, userPrompt);\n const signature = \"\\n\\nπ€ Commit generated with [GitaiJS](https://github.com/leandrosilvaferreira/gitai-js)\";\n return commitMessage + signature;\n }\n \n // Logic for release notes (used by releaser.ts)\n async generateReleaseNotes(commits: string, newVersion: string, tag: string): Promise<string> {\n const systemPrompt = `\nYou are an assistant that helps generate release notes for a Git repository.\nCommit messages should be organized into categories such as New Features, Bug Fixes, and Other Changes.\nThe output must be a markdown-formatted text according to the provided template, with no additional comments or formatting.\n`.trim();\n \n const userPrompt = `\nYou are an assistant that helps generate release notes for a Git repository.\nBelow are the commits since the last tag ${tag}.\nPlease organize the commits into the following categories: New Features, Bug Fixes, and Other Changes.\nGenerate a release message in markdown format in the language '${this.config.language}' using the following template:\n\n\\`\\`\\`\n# Release ${newVersion}\n<SUMMARY/>\n\n### New Features\n- Description of new features (commits).\n\n### Bug Fixes\n- Description of bug fixes (commits).\n\n### Other Changes\n- Description of other changes (commits).\n\nWe thank all the contributors who made this release possible! For more details, please refer to the complete version notes.\n\n**Full Changelog:** [See commits for v${newVersion}](https://github.com/leandrosilvaferreira/gitai-js/compare/${tag}...v${newVersion})\n\\`\\`\\`\n\nCommits:\n${commits}\n\nImportant rules:\n - The generated content must be in the language '${this.config.language}'.\n - Replace <SUMMARY/> in the template with a brief and enthusiastic summary of the changes made since the last tag ${tag}.\n - DO NOT add any additional comments or explanations.\n - DO NOT use symbols like \\`\\`\\` to denote commit messages.\n - The message must be clear, concise, and well-organized.\n - Remember to follow the provided template.\n\nIf the instructions are not followed correctly, the result will not be accepted.\n`.trim();\n\n return this.callApi(systemPrompt, userPrompt);\n\n }\n\n\n private async callApi(systemPrompt: string, userPrompt: string): Promise<string> {\n if (this.config.provider === 'openai' && this.openai) {\n logger.ai(`Provider: openai - Model: ${this.config.model}`);\n \n const isNewModel = ['o1', 'o3', 'gpt-5'].some(prefix => this.config.model.startsWith(prefix));\n const tokenParam = isNewModel ? 'max_completion_tokens' : 'max_tokens';\n \n const completion = await this.openai.chat.completions.create({\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt }\n ],\n model: this.config.model,\n temperature: 0.5,\n top_p: 1.0,\n frequency_penalty: 0.0,\n presence_penalty: 0.0,\n [tokenParam]: 500,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n\n return completion.choices[0].message.content?.trim() || '';\n\n } else if (this.config.provider === 'groq' && this.groq) {\n logger.ai(`Provider: groq - Model: ${this.config.model}`);\n const completion = await this.groq.chat.completions.create({\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt }\n ],\n model: this.config.model,\n temperature: 0.5,\n max_tokens: 500,\n top_p: 1.0,\n frequency_penalty: 0.0,\n presence_penalty: 0.0\n });\n return completion.choices[0].message.content?.trim() || '';\n\n } else if (this.config.provider === 'anthropic' && this.anthropic) {\n logger.ai(`Provider: anthropic - Model: ${this.config.model}`);\n const message = await this.anthropic.messages.create({\n model: this.config.model,\n max_tokens: 500,\n temperature: 0.5,\n system: systemPrompt,\n messages: [\n { role: 'user', content: userPrompt }\n ]\n });\n const contentBlock = message.content[0];\n if (contentBlock.type === 'text') {\n return contentBlock.text.trim();\n }\n return '';\n }\n\n return '';\n }\n}\n","import chalk from 'chalk';\n\nexport const logger = {\n header: (message: string) => {\n console.log(chalk.cyan.bold(`π ${message}`));\n },\n success: (message: string) => {\n console.log(chalk.green.bold(`β
${message}`));\n },\n info: (message: string) => {\n console.log(chalk.blue.bold(`βΉοΈ ${message}`));\n },\n warning: (message: string) => {\n console.log(chalk.yellow.bold(`β οΈ ${message}`));\n },\n error: (message: string) => {\n console.log(chalk.red.bold(`β ${message}`));\n },\n git: (message: string) => {\n console.log(chalk.magenta.bold(`π ${message}`));\n },\n ai: (message: string) => {\n console.log(chalk.cyan.bold(`π€ ${message}`));\n },\n commit: (message: string) => {\n console.log('\\n' + chalk.bgBlue.white.bold(' Generated commit message: ') + '\\n');\n console.log(chalk.white.bold(message));\n console.log();\n }\n};\n","import fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport semver from 'semver';\n\nimport { engines } from '../version.js';\n\nexport interface AppConfig {\n LANGUAGE: string;\n PROVIDER: string;\n API_KEY: string;\n MODEL: string;\n}\n\nexport const CONFIG_PATH = path.join(os.homedir(), '.gitai');\n\nexport const checkConfigExists = (): boolean => {\n try {\n return fs.existsSync(CONFIG_PATH);\n } catch {\n return false;\n }\n};\n\nexport const loadConfig = (): AppConfig => {\n if (!checkConfigExists()) {\n throw new Error(`Configuration file not found at ${CONFIG_PATH}`);\n }\n const content = fs.readFileSync(CONFIG_PATH, 'utf-8');\n const config: Record<string, string> = {};\n content.split('\\n').forEach(line => {\n // Simple env parsing\n const [key, ...value] = line.split('=');\n if (key && value && key.trim()) {\n // Rejoin value in case it contained =\n let val = value.join('=').trim();\n \n // Remove quotes if present\n if (val.startsWith('\"') && val.endsWith('\"')) {\n val = val.slice(1, -1);\n }\n if (val.startsWith(\"'\") && val.endsWith(\"'\")) {\n val = val.slice(1, -1);\n }\n\n config[key.trim()] = val;\n }\n });\n return config as unknown as AppConfig;\n};\n\nexport const saveConfig = (config: AppConfig): void => {\n const content = Object.entries(config)\n .map(([key, value]) => `${key}=${value}`)\n .join('\\n');\n \n // Write with secure permissions (600 - read/write only by owner) since it contains API keys\n fs.writeFileSync(CONFIG_PATH, content, { mode: 0o600 });\n};\n\nexport const validateNodeVersion = (): boolean => {\n const requiredVersion = engines.node;\n return semver.satisfies(process.version, requiredVersion);\n};\n","export const version = '0.0.11';\nexport const name = 'gitai';\nexport const engines = {\n node: '>=18'\n};\n","import { execa } from 'execa';\nimport fs from 'fs/promises';\nimport os from 'os';\nimport path from 'path';\nimport { logger } from './logger.js';\n\nexport async function runGitCommand(args: string[], cwd: string = process.cwd(), exitOnError: boolean = true): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n try {\n const result = await execa('git', args, { cwd, reject: false });\n \n if (result.exitCode !== 0) {\n if (exitOnError) {\n logger.error(`Error executing command: git ${args.join(' ')}`);\n logger.error(`Standard output: ${result.stdout}`);\n logger.error(`Error output: ${result.stderr}`);\n process.exit(1);\n }\n }\n return {\n stdout: result.stdout.trim(),\n stderr: result.stderr.trim(),\n exitCode: result.exitCode ?? 1\n };\n } catch (error: unknown) {\n if (exitOnError) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Unexpected error executing git command: ${errorMessage}`);\n process.exit(1);\n }\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { stdout: '', stderr: errorMessage, exitCode: 1 };\n }\n}\n\nexport async function hasUncommittedChanges(cwd: string): Promise<boolean> {\n const { stdout } = await runGitCommand(['status', '--porcelain'], cwd);\n return stdout.length > 0;\n}\n\nexport async function isBranchAhead(cwd: string): Promise<boolean> {\n const { stdout } = await runGitCommand(['status', '-uno'], cwd);\n return stdout.includes('Your branch is ahead') || stdout.includes('Seu branch estΓ‘ Γ frente');\n}\n\nexport async function performGitPull(cwd: string): Promise<boolean> {\n const { stdout, stderr, exitCode } = await runGitCommand(['pull'], cwd, false);\n\n if (exitCode !== 0) {\n if (stdout.includes('CONFLICT') || stdout.includes('CONFLITO') || stderr.includes('CONFLICT') || stderr.includes('CONFLITO')) {\n logger.warning(\"Conflitos detectados durante git pull:\");\n logger.error(stdout || stderr);\n return false;\n } else {\n logger.error(`Error executing git pull: ${stdout || stderr}`);\n process.exit(1);\n }\n }\n logger.success(\"Git pull executed successfully.\");\n return true;\n}\n\nexport async function commitChanges(commitMessage: string, cwd: string): Promise<void> {\n await runGitCommand(['add', '.'], cwd);\n \n // Write commit message to temp file to handle special characters correctly\n const tempDir = os.tmpdir();\n const tempFilePath = path.join(tempDir, `gitai_commit_${Date.now()}.txt`);\n \n try {\n await fs.writeFile(tempFilePath, commitMessage, 'utf-8');\n await runGitCommand(['commit', '-F', tempFilePath], cwd);\n } finally {\n try {\n await fs.unlink(tempFilePath);\n } catch {\n // Ignore error if cleanup fails\n }\n }\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { logger } from './logger.js';\n\nconst indicatorFiles: Record<string, string[]> = {\n 'Node.js': ['package.json', 'yarn.lock', 'package-lock.json', 'npm-shrinkwrap.json'],\n 'Python': ['requirements.txt', 'Pipfile', 'pyproject.toml', 'setup.py', 'setup.cfg', 'manage.py'],\n 'Java': ['pom.xml', 'build.gradle', 'build.gradle.kts', 'build.xml', '.java-version'],\n 'Go': ['go.mod', 'Gopkg.lock'],\n 'PHP': ['composer.json', 'composer.lock', 'index.php'],\n 'Ruby': ['Gemfile', 'Gemfile.lock', 'Rakefile', 'config.ru', '.ruby-version'],\n 'Rust': ['Cargo.toml', 'Cargo.lock'],\n 'Haskell': ['stack.yaml', 'cabal.project'],\n 'Swift': ['Package.swift'],\n 'Elixir': ['mix.exs'],\n 'Dart': ['pubspec.yaml'],\n 'Scala': ['build.sbt'],\n 'Perl': ['Makefile.PL', 'Build.PL'],\n 'R': ['.Rproj']\n};\n\nconst extensionIndicators: Record<string, string[]> = {\n 'C#': ['.csproj', '.sln'],\n 'Haskell': ['.cabal'],\n 'Swift': ['.xcodeproj', '.xcworkspace'],\n 'Kotlin': ['.kt', '.kts'],\n 'C/C++': ['.c', '.cpp', '.h', '.hpp'],\n 'JavaScript': ['.js', '.jsx'],\n 'TypeScript': ['.ts', '.tsx'],\n 'Python': ['.py'],\n 'Java': ['.java']\n};\n\nconst languageEmojis: Record<string, string> = {\n 'Node.js': 'π’',\n 'Python': 'π',\n 'Java': 'β',\n 'Go': 'πΉ',\n 'PHP': 'π',\n 'Ruby': 'π',\n 'Rust': 'π¦',\n 'Haskell': 'π©',\n 'Swift': 'π',\n 'Elixir': 'π§',\n 'Dart': 'π―',\n 'Scala': 'βοΈ',\n 'Perl': 'πͺ',\n 'R': 'π',\n 'C#': 'π·',\n 'C/C++': 'βοΈ',\n 'JavaScript': 'π¨',\n 'TypeScript': 'π·',\n 'Unknown': 'β'\n};\n\nexport function getLanguageEmoji(language: string): string {\n return languageEmojis[language] || 'β';\n}\n\nexport function printDetectedLanguage(language: string): void {\n const emoji = getLanguageEmoji(language);\n logger.info(`${emoji} Linguagem detectada: ${language}\\n`);\n}\n\nexport async function detectProjectLanguage(projectPath: string): Promise<string> {\n try {\n const rootFiles = await fs.readdir(projectPath);\n\n // Check for indicator files in the project root\n for (const [language, indicators] of Object.entries(indicatorFiles)) {\n for (const indicator of indicators) {\n if (indicator.includes(path.sep)) {\n // This logic handles nested paths in indicators if necessary, \n // though node path module might be different. \n // Keeping it simple as per original python logic which used os.path.sep\n // For now, let's assume flat filenames for simplicity unless we see complex ones\n // The python code did: if os.path.sep in indicator...\n } else {\n if (rootFiles.includes(indicator)) {\n return language;\n }\n }\n }\n }\n\n // Check for file extensions in the project root\n for (const [language, extensions] of Object.entries(extensionIndicators)) {\n for (const file of rootFiles) {\n if (extensions.some(ext => file.endsWith(ext))) {\n return language;\n }\n }\n }\n\n // Recursive check logic from python is a bit heavy (os.walk), \n // let's implement a lighter version or skip if not strictly needed.\n // The original scanned the whole tree which can be slow for node_modules.\n // Let's implement a limited depth scan if root check failed.\n // For efficiency, maybe just skip the deep scan for this first version \n // unless the user specifically wants it.\n // Gitai.py uses os.walk which is recursive. \n // Let's assume Unknown for now if not found in root to avoid performance issues in huge JS projects.\n \n return \"Unknown\";\n\n } catch {\n return \"Unknown\";\n }\n}\n","import chalk from 'chalk';\nimport { execa } from 'execa';\nimport inquirer from 'inquirer';\nimport { AppConfig, CONFIG_PATH, saveConfig } from './config.js';\n\nimport { version } from '../version.js';\n\nexport async function runSetup(): Promise<AppConfig> {\n console.clear();\n console.log(chalk.bold.blue(`\\nπ Welcome to GitAI v${version} Setup! π`));\n console.log(chalk.dim('Let\\'s get you ready to code with AI assistance.\\n'));\n\n // 1. Check Prerequisites\n try {\n await execa('git', ['--version']);\n console.log(chalk.green('β
Git is installed!'));\n } catch {\n console.log(chalk.red('β Git is NOT installed or not accessible from PATH.'));\n console.log(chalk.yellow('Please install Git before proceeding.'));\n process.exit(1);\n }\n \n console.log(chalk.cyan('\\nβοΈ Global Configuration (saved to ' + CONFIG_PATH + ')\\n'));\n\n // 2. Prompts\n // Inquirer v12+ types might need check, but standard array syntax usually persists or we use separate imports.\n // Assuming standard prompt syntax works for this version as it is the default export typically.\n \n const answers = await inquirer.prompt([\n {\n type: 'list',\n name: 'LANGUAGE',\n message: 'What language should the AI use for commit messages?',\n choices: [\n { name: 'English', value: 'en' },\n { name: 'Portuguese (Brasil)', value: 'pt-br' },\n { name: 'Spanish', value: 'es' },\n { name: 'French', value: 'fr' },\n { name: 'German', value: 'de' },\n { name: 'Italian', value: 'it' },\n { name: 'Chinese', value: 'zh' },\n { name: 'Japanese', value: 'ja' },\n { name: 'Korean', value: 'ko' }\n ],\n default: 'en'\n },\n {\n type: 'list',\n name: 'PROVIDER',\n message: 'Which AI Provider do you want to use?',\n choices: [\n { name: 'OpenAI', value: 'openai' },\n { name: 'Anthropic', value: 'anthropic' },\n { name: 'Groq', value: 'groq' }\n ],\n default: 'openai'\n },\n {\n type: 'password',\n name: 'API_KEY',\n message: 'Enter your API Key:',\n mask: '*',\n validate: (input: string) => input.length > 0 ? true : 'API Key is required'\n },\n {\n type: 'input',\n name: 'MODEL',\n message: 'Model ID (e.g., gpt-4o, claude-3-5-sonnet):',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n default: (answers: any) => {\n if (answers.PROVIDER === 'openai') return 'gpt-4o';\n if (answers.PROVIDER === 'anthropic') return 'claude-3-5-sonnet-20240620';\n if (answers.PROVIDER === 'groq') return 'llama3-70b-8192';\n return 'gpt-4o';\n }\n }\n ]);\n\n const config: AppConfig = {\n LANGUAGE: answers.LANGUAGE,\n PROVIDER: answers.PROVIDER,\n API_KEY: answers.API_KEY,\n MODEL: answers.MODEL\n };\n\n saveConfig(config);\n\n console.log(chalk.green('\\nβ¨ Configuration saved successfully! β¨'));\n console.log(chalk.dim('You are all set. Running GitAI...\\n'));\n\n return config;\n}\n"],"mappings":"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","names":["chalk","Command","path","Anthropic","Groq","OpenAI","chalk","logger","message","AIService","config","OpenAI","Groq","Anthropic","logger","diffOutput","projectLanguage","baseMessage","systemPrompt","userPrompt","commits","newVersion","tag","tokenParam","prefix","contentBlock","fs","os","path","semver","version","name","engines","CONFIG_PATH","path","os","checkConfigExists","fs","loadConfig","content","config","line","key","value","val","saveConfig","validateNodeVersion","requiredVersion","engines","semver","execa","fs","os","path","runGitCommand","args","cwd","exitOnError","result","execa","logger","error","errorMessage","hasUncommittedChanges","stdout","isBranchAhead","performGitPull","stderr","exitCode","commitChanges","commitMessage","tempDir","os","tempFilePath","path","fs","fs","path","indicatorFiles","extensionIndicators","languageEmojis","getLanguageEmoji","language","printDetectedLanguage","emoji","logger","detectProjectLanguage","projectPath","rootFiles","fs","indicators","indicator","path","extensions","file","ext","chalk","execa","inquirer","runSetup","chalk","version","execa","CONFIG_PATH","answers","inquirer","input","config","saveConfig","validateNodeVersion","chalk","engines","program","Command","name","version","projectPathArg","baseMessageArg","options","config","checkConfigExists","loadConfig","runSetup","error","errorMessage","logger","projectPath","path","aiService","AIService","hasUncommittedChanges","projectLanguage","detectProjectLanguage","printDetectedLanguage","diffOutput","runGitCommand","baseMessage","commitMessage","commitChanges","performGitPull","isBranchAhead"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@notyped/gitai",
|
|
3
|
+
"version": "0.0.11",
|
|
4
|
+
"description": "AI-powered git commit assistant and release note generator",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"gitai": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"start": "node dist/index.js",
|
|
17
|
+
"build": "npm run lint && tsup",
|
|
18
|
+
"dev": "tsup --watch",
|
|
19
|
+
"lint": "eslint 'src/**/*.{ts,js}' && tsc --noEmit",
|
|
20
|
+
"format": "prettier --write 'src/**/*.{ts,js}'",
|
|
21
|
+
"release-notes": "npm run lint && tsx src/releaser.ts",
|
|
22
|
+
"release": "npm run lint && tsx scripts/release-flow.ts"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"git",
|
|
26
|
+
"ai",
|
|
27
|
+
"commit",
|
|
28
|
+
"assistant"
|
|
29
|
+
],
|
|
30
|
+
"author": "Leandro Silva Ferreira",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/leandrosilvaferreira/gitai-js"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@eslint/js": "^9.39.2",
|
|
38
|
+
"@types/node": "^22.0.0",
|
|
39
|
+
"eslint": "^9.0.0",
|
|
40
|
+
"globals": "^17.2.0",
|
|
41
|
+
"prettier": "^3.0.0",
|
|
42
|
+
"ts-node": "^10.9.2",
|
|
43
|
+
"tsup": "^8.5.1",
|
|
44
|
+
"tsx": "^4.21.0",
|
|
45
|
+
"typescript": "^5.0.0",
|
|
46
|
+
"typescript-eslint": "^8.54.0"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@anthropic-ai/sdk": "^0.36.3",
|
|
50
|
+
"@types/semver": "^7.7.1",
|
|
51
|
+
"chalk": "^5.4.1",
|
|
52
|
+
"commander": "^13.1.0",
|
|
53
|
+
"dotenv": "^16.4.7",
|
|
54
|
+
"execa": "^9.5.2",
|
|
55
|
+
"groq-sdk": "^0.15.0",
|
|
56
|
+
"inquirer": "^12.4.1",
|
|
57
|
+
"openai": "^4.82.0",
|
|
58
|
+
"semver": "^7.7.3"
|
|
59
|
+
},
|
|
60
|
+
"type": "module",
|
|
61
|
+
"engines": {
|
|
62
|
+
"node": ">=18"
|
|
63
|
+
}
|
|
64
|
+
}
|