gitai-local 1.0.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,18 @@
1
+ MIT License
2
+ Copyright (c) 2026 GitAI
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18
+ SOFTWARE.
@@ -0,0 +1,226 @@
1
+ Metadata-Version: 2.4
2
+ Name: gitai-local
3
+ Version: 1.0.0
4
+ Summary: AI-powered conventional commit message generator running 100% locally
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/PabloSalinasDev/GitAI-CLI
7
+ Classifier: Development Status :: 5 - Production/Stable
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Topic :: Software Development :: Version Control :: Git
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: llama-cpp-python[server]>=0.3.0
17
+ Requires-Dist: httpx>=0.27.0
18
+ Requires-Dist: psutil>=6.0.0
19
+ Requires-Dist: colorama>=0.4.6
20
+ Dynamic: license-file
21
+
22
+ # GitAI
23
+
24
+ An offline, privacy-first CLI tool that automatically generates structured Git commit messages using a local LLM via `llama.cpp`. No API keys required, no data leaves your machine.
25
+
26
+ <p align="center">
27
+ <a href="https://pypi.org/project/gitai-cli/">
28
+ <img src="https://img.shields.io/badge/Install-PyPI-blue?style=for-the-badge&logo=pypi" alt="Install from PyPI">
29
+ </a>
30
+ &nbsp;&nbsp;&nbsp;&nbsp;
31
+ <a href="https://github.com/PabloSalinasDev/GitAI-CLI/issues">
32
+ <img src="https://img.shields.io/badge/Report-Error-red?style=for-the-badge&logo=github" alt="Report Error">
33
+ </a>
34
+ </p>
35
+
36
+ ---
37
+
38
+ ## Why GitAI? (Educational Purpose)
39
+
40
+ Starting out in software development requires absorbing dozens of industry best practices simultaneously. Adopting the **Conventional Commits** standard right from the beginning often causes friction and leads to wasted time staring at a blank terminal screen wondering how to phrase a change.
41
+
42
+ GitAI was built to act as an **invisible mentor inside your console**, specifically designed for developers looking to professionalize their daily workflow without losing focus on writing code.
43
+
44
+ The benefit of implementing this CLI is twofold:
45
+
46
+ * **Immediate Impact (Professionalism):** It resolves technical nomenclature in just a few seconds, ensuring a pristine, clean, and standardized Git history. This is ideal for making your portfolio stand out to recruiters reviewing your GitHub repositories.
47
+ * **Passive Learning (Long-term):** It works through imitation and consistency. By interactively auditing how the AI categorizes your syntax changes with precise tags (`feat`, `fix`, `refactor`), a developer's brain naturally absorbs the pattern over time, learning how to structure correct commits organically.
48
+
49
+ ---
50
+
51
+ ## Features
52
+
53
+ - **100% Local Ingestion**: Uses `llama-cpp-python` to run model inference completely offline via a background HTTP server on `localhost:8089`.
54
+ - **Conventional Commits**: Enforces the standard `type: description` format (e.g., `feat: add user authentication`).
55
+ - **Diff-Aware Context**: Inspects staged changes and file names to provide accurate context.
56
+ - **Initial Commit Detection**: Automatically detects the first commit of a repository and uses the README and file list as context instead of a diff.
57
+ - **Smart Language Memory**: Learns your language preference (English or Spanish) per repository using Git's native configuration system (`gitai.lang`), avoiding repetitive prompts.
58
+ - **Windows & UTF-8 Native**: Fully hardened against character encoding issues (`ñ`, acentos, `¿`) when generating or editing messages in Windows consoles.
59
+
60
+ ## How it works
61
+
62
+ 1. On first use, run `gitai init` to download the AI model (~4.7 GB).
63
+ 2. At the start of each work session, run `gitai start` inside your repo. This loads the model into RAM as a background daemon and asks for your language preference if not already set.
64
+ 3. After staging changes, run `gitai`. It feeds the diff (or initial commit context) into the model and proposes a commit message.
65
+ 4. At the end of your session, run `gitai out` to stop the daemon and free RAM.
66
+
67
+ ---
68
+
69
+ ### Real-World Benchmarks & Reference Metrics
70
+
71
+ ![GitAI Terminal Benchmark](assets/gitai-terminal-benchmark.png)
72
+
73
+ The following metrics are **estimates based on empirical testing**. Actual execution times are non-linear and may vary depending on current CPU background load...
74
+
75
+ ---
76
+
77
+ ## Project structure
78
+
79
+ ```
80
+ gitai/
81
+ ├── assets/
82
+ ├── gitai/
83
+ │ ├── __init__.py
84
+ │ ├── config.py ← model path, download logic, language config
85
+ │ ├── main.py ← CLI logic, user interaction
86
+ │ └── llm_client.py ← daemon management and inference via HTTP
87
+ ├── pyproject.toml ← package definition and dependencies
88
+ └── README.md
89
+ ```
90
+
91
+ ## Installation (for Python developers)
92
+
93
+ First, install pipx if you don't have it:
94
+
95
+ ```bash
96
+ pip install pipx
97
+ python -m pipx ensurepath
98
+ ```
99
+
100
+ > After running `ensurepath`, restart your terminal.
101
+
102
+ Then install gitai globally:
103
+
104
+ ```bash
105
+ pipx install --force .
106
+ ```
107
+
108
+ ## Setup (one time)
109
+
110
+ Download the AI model (~4.7 GB). This only needs to be done once:
111
+
112
+ ```bash
113
+ gitai init
114
+ ```
115
+
116
+ > The model (`Qwen2.5-Coder-7B-Instruct-Q4_K_M.gguf`) is stored in `%LOCALAPPDATA%\gitai\models`.
117
+
118
+ ---
119
+
120
+ ## Usage
121
+
122
+ ### Start a work session
123
+
124
+ Run this once per session inside your repository. Loads the model into RAM and sets the language for the repo if not already configured:
125
+
126
+ ```bash
127
+ gitai start
128
+ ```
129
+
130
+ ### Generate a commit message
131
+
132
+ ```bash
133
+ git add .
134
+ gitai
135
+ ```
136
+
137
+ ### End a work session
138
+
139
+ Stops the background daemon and frees RAM:
140
+
141
+ ```bash
142
+ gitai out
143
+ ```
144
+
145
+ ---
146
+
147
+ ## Command reference
148
+
149
+ | Command | Description |
150
+ |---------|-------------|
151
+ | `gitai init` | Downloads the AI model (first time only) |
152
+ | `gitai start` | Loads the model into RAM, sets repo language |
153
+ | `gitai` | Generates and commits staged changes |
154
+ | `gitai out` | Stops the background daemon, frees RAM |
155
+
156
+ ---
157
+
158
+ ## Commit types used
159
+
160
+ | Type | When to use |
161
+ |------|-------------|
162
+ | feat | New feature |
163
+ | fix | Bug fix |
164
+ | docs | Documentation changes |
165
+ | style | Formatting, no logic change |
166
+ | refactor | Code refactor |
167
+ | test | Adding or fixing tests |
168
+ | chore | Build, dependencies, config |
169
+ | perf | Performance improvement |
170
+ | ci | CI/CD changes |
171
+ | build | Build system changes |
172
+
173
+ ---
174
+
175
+ ## Requirements
176
+
177
+ - Python 3.10+
178
+ - Git installed
179
+ - ~4.7 GB disk space for the model
180
+
181
+ ## Performance & Efficiency
182
+
183
+ Commit message generation runs **100% locally and entirely on your CPU**. No external APIs, no data leaks, and no heavy CUDA/ROCm GPU dependencies required.
184
+
185
+ Because inference happens directly on your processor, generation times are non-linear and scale based on your hardware architecture (specifically CPU single-core speed and RAM bandwidth), as well as the complexity of the git diff.
186
+
187
+ ### Real-World Benchmarks & Reference Metrics (Qwen 2.5 Coder 7B - Q4_K_M)
188
+
189
+ The following metrics are **estimates based on empirical testing**. Actual execution times are non-linear and may vary depending on current CPU background load and system memory availability.
190
+
191
+ Based on extensive stress-testing on standard consumer hardware (e.g., Intel i7 7th Gen with 16GB DDR4 @ 2400MHz), you can expect the following operational ranges.
192
+
193
+ | Hardware Profile | Context Size | Estimated Time * | Commit Accuracy |
194
+ |------------------|--------------|------------------|-----------------|
195
+ | **Modern Desktop / Laptop**<br>*(Ryzen 5/7, Core i5/i7 11th+ Gen, DDR5)* | Small to Large Diffs | **~8 – 20 seconds** | ~98% |
196
+ | **Older / Standard Hardware**<br>*(Legacy Intel i7, DDR4 @ 2400MHz)* | Small to Medium Diffs | **~20 – 40 seconds** | ~98% |
197
+ | **Stress Test / Massive Changes**<br>*(Legacy Hardware + Dense Diffs)* | Large Multi-file Diffs | **~40 – 70 seconds** | ~98% |
198
+
199
+ > **Note on Performance:** Times are heavily bound to RAM clock speed and single-core efficiency. A dense, multi-file diff analyzed on legacy hardware might occasionally touch the upper boundary of the stress test zone. However, GitAI's built-in traffic manager ensures payloads remain strictly bounded to keep local execution controlled and predictable.
200
+
201
+ > **Predictable Execution Cap:** GitAI features a built-in traffic management engine. By enforcing a hard limit on filtered context sizes, the CLI prevents the LLM from entering runaway processing loops. Even during massive codebase refactors, the input payload is strictly constrained to ensure a reliable, bounded local user experience without ever freezing your terminal.
202
+
203
+ ### The GitAI Smart Token Optimization
204
+
205
+ Why are these times so consistent? GitAI does not just dump raw data into the LLM. It includes a custom pre-processing pipeline that strips out compiler noise, binary files, white spaces, and structural brackets before sending the payload.
206
+
207
+ * **Linear vs. Deductive Processing:** Testing proved that sending a complete, clean code block up to 2500 characters is significantly faster than truncating it too early. By providing the model with full, clean context, the LLM processes the data linearly instead of wasting CPU cycles trying to "guess" missing code structures. This balance cuts down processing overhead by up to 30 seconds on older machines while boosting commit accuracy to a staggering **98%**.
208
+
209
+ ## Dependencies
210
+
211
+ | Package | Purpose |
212
+ |---------|---------|
213
+ | llama-cpp-python | Run the local AI model as an HTTP server |
214
+ | httpx | Download the model and communicate with the daemon |
215
+ | psutil | Stop the background daemon (`gitai out`) |
216
+ | colorama | Handle cross-platform terminal text colorization and visual hierarchy |
217
+
218
+ ---
219
+
220
+ ## License
221
+
222
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
223
+
224
+ ---
225
+
226
+ *Developed by [Pablo Salinas](https://github.com/PabloSalinasDev)* - PyBloSoft © 2026
@@ -0,0 +1,205 @@
1
+ # GitAI
2
+
3
+ An offline, privacy-first CLI tool that automatically generates structured Git commit messages using a local LLM via `llama.cpp`. No API keys required, no data leaves your machine.
4
+
5
+ <p align="center">
6
+ <a href="https://pypi.org/project/gitai-cli/">
7
+ <img src="https://img.shields.io/badge/Install-PyPI-blue?style=for-the-badge&logo=pypi" alt="Install from PyPI">
8
+ </a>
9
+ &nbsp;&nbsp;&nbsp;&nbsp;
10
+ <a href="https://github.com/PabloSalinasDev/GitAI-CLI/issues">
11
+ <img src="https://img.shields.io/badge/Report-Error-red?style=for-the-badge&logo=github" alt="Report Error">
12
+ </a>
13
+ </p>
14
+
15
+ ---
16
+
17
+ ## Why GitAI? (Educational Purpose)
18
+
19
+ Starting out in software development requires absorbing dozens of industry best practices simultaneously. Adopting the **Conventional Commits** standard right from the beginning often causes friction and leads to wasted time staring at a blank terminal screen wondering how to phrase a change.
20
+
21
+ GitAI was built to act as an **invisible mentor inside your console**, specifically designed for developers looking to professionalize their daily workflow without losing focus on writing code.
22
+
23
+ The benefit of implementing this CLI is twofold:
24
+
25
+ * **Immediate Impact (Professionalism):** It resolves technical nomenclature in just a few seconds, ensuring a pristine, clean, and standardized Git history. This is ideal for making your portfolio stand out to recruiters reviewing your GitHub repositories.
26
+ * **Passive Learning (Long-term):** It works through imitation and consistency. By interactively auditing how the AI categorizes your syntax changes with precise tags (`feat`, `fix`, `refactor`), a developer's brain naturally absorbs the pattern over time, learning how to structure correct commits organically.
27
+
28
+ ---
29
+
30
+ ## Features
31
+
32
+ - **100% Local Ingestion**: Uses `llama-cpp-python` to run model inference completely offline via a background HTTP server on `localhost:8089`.
33
+ - **Conventional Commits**: Enforces the standard `type: description` format (e.g., `feat: add user authentication`).
34
+ - **Diff-Aware Context**: Inspects staged changes and file names to provide accurate context.
35
+ - **Initial Commit Detection**: Automatically detects the first commit of a repository and uses the README and file list as context instead of a diff.
36
+ - **Smart Language Memory**: Learns your language preference (English or Spanish) per repository using Git's native configuration system (`gitai.lang`), avoiding repetitive prompts.
37
+ - **Windows & UTF-8 Native**: Fully hardened against character encoding issues (`ñ`, acentos, `¿`) when generating or editing messages in Windows consoles.
38
+
39
+ ## How it works
40
+
41
+ 1. On first use, run `gitai init` to download the AI model (~4.7 GB).
42
+ 2. At the start of each work session, run `gitai start` inside your repo. This loads the model into RAM as a background daemon and asks for your language preference if not already set.
43
+ 3. After staging changes, run `gitai`. It feeds the diff (or initial commit context) into the model and proposes a commit message.
44
+ 4. At the end of your session, run `gitai out` to stop the daemon and free RAM.
45
+
46
+ ---
47
+
48
+ ### Real-World Benchmarks & Reference Metrics
49
+
50
+ ![GitAI Terminal Benchmark](assets/gitai-terminal-benchmark.png)
51
+
52
+ The following metrics are **estimates based on empirical testing**. Actual execution times are non-linear and may vary depending on current CPU background load...
53
+
54
+ ---
55
+
56
+ ## Project structure
57
+
58
+ ```
59
+ gitai/
60
+ ├── assets/
61
+ ├── gitai/
62
+ │ ├── __init__.py
63
+ │ ├── config.py ← model path, download logic, language config
64
+ │ ├── main.py ← CLI logic, user interaction
65
+ │ └── llm_client.py ← daemon management and inference via HTTP
66
+ ├── pyproject.toml ← package definition and dependencies
67
+ └── README.md
68
+ ```
69
+
70
+ ## Installation (for Python developers)
71
+
72
+ First, install pipx if you don't have it:
73
+
74
+ ```bash
75
+ pip install pipx
76
+ python -m pipx ensurepath
77
+ ```
78
+
79
+ > After running `ensurepath`, restart your terminal.
80
+
81
+ Then install gitai globally:
82
+
83
+ ```bash
84
+ pipx install --force .
85
+ ```
86
+
87
+ ## Setup (one time)
88
+
89
+ Download the AI model (~4.7 GB). This only needs to be done once:
90
+
91
+ ```bash
92
+ gitai init
93
+ ```
94
+
95
+ > The model (`Qwen2.5-Coder-7B-Instruct-Q4_K_M.gguf`) is stored in `%LOCALAPPDATA%\gitai\models`.
96
+
97
+ ---
98
+
99
+ ## Usage
100
+
101
+ ### Start a work session
102
+
103
+ Run this once per session inside your repository. Loads the model into RAM and sets the language for the repo if not already configured:
104
+
105
+ ```bash
106
+ gitai start
107
+ ```
108
+
109
+ ### Generate a commit message
110
+
111
+ ```bash
112
+ git add .
113
+ gitai
114
+ ```
115
+
116
+ ### End a work session
117
+
118
+ Stops the background daemon and frees RAM:
119
+
120
+ ```bash
121
+ gitai out
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Command reference
127
+
128
+ | Command | Description |
129
+ |---------|-------------|
130
+ | `gitai init` | Downloads the AI model (first time only) |
131
+ | `gitai start` | Loads the model into RAM, sets repo language |
132
+ | `gitai` | Generates and commits staged changes |
133
+ | `gitai out` | Stops the background daemon, frees RAM |
134
+
135
+ ---
136
+
137
+ ## Commit types used
138
+
139
+ | Type | When to use |
140
+ |------|-------------|
141
+ | feat | New feature |
142
+ | fix | Bug fix |
143
+ | docs | Documentation changes |
144
+ | style | Formatting, no logic change |
145
+ | refactor | Code refactor |
146
+ | test | Adding or fixing tests |
147
+ | chore | Build, dependencies, config |
148
+ | perf | Performance improvement |
149
+ | ci | CI/CD changes |
150
+ | build | Build system changes |
151
+
152
+ ---
153
+
154
+ ## Requirements
155
+
156
+ - Python 3.10+
157
+ - Git installed
158
+ - ~4.7 GB disk space for the model
159
+
160
+ ## Performance & Efficiency
161
+
162
+ Commit message generation runs **100% locally and entirely on your CPU**. No external APIs, no data leaks, and no heavy CUDA/ROCm GPU dependencies required.
163
+
164
+ Because inference happens directly on your processor, generation times are non-linear and scale based on your hardware architecture (specifically CPU single-core speed and RAM bandwidth), as well as the complexity of the git diff.
165
+
166
+ ### Real-World Benchmarks & Reference Metrics (Qwen 2.5 Coder 7B - Q4_K_M)
167
+
168
+ The following metrics are **estimates based on empirical testing**. Actual execution times are non-linear and may vary depending on current CPU background load and system memory availability.
169
+
170
+ Based on extensive stress-testing on standard consumer hardware (e.g., Intel i7 7th Gen with 16GB DDR4 @ 2400MHz), you can expect the following operational ranges.
171
+
172
+ | Hardware Profile | Context Size | Estimated Time * | Commit Accuracy |
173
+ |------------------|--------------|------------------|-----------------|
174
+ | **Modern Desktop / Laptop**<br>*(Ryzen 5/7, Core i5/i7 11th+ Gen, DDR5)* | Small to Large Diffs | **~8 – 20 seconds** | ~98% |
175
+ | **Older / Standard Hardware**<br>*(Legacy Intel i7, DDR4 @ 2400MHz)* | Small to Medium Diffs | **~20 – 40 seconds** | ~98% |
176
+ | **Stress Test / Massive Changes**<br>*(Legacy Hardware + Dense Diffs)* | Large Multi-file Diffs | **~40 – 70 seconds** | ~98% |
177
+
178
+ > **Note on Performance:** Times are heavily bound to RAM clock speed and single-core efficiency. A dense, multi-file diff analyzed on legacy hardware might occasionally touch the upper boundary of the stress test zone. However, GitAI's built-in traffic manager ensures payloads remain strictly bounded to keep local execution controlled and predictable.
179
+
180
+ > **Predictable Execution Cap:** GitAI features a built-in traffic management engine. By enforcing a hard limit on filtered context sizes, the CLI prevents the LLM from entering runaway processing loops. Even during massive codebase refactors, the input payload is strictly constrained to ensure a reliable, bounded local user experience without ever freezing your terminal.
181
+
182
+ ### The GitAI Smart Token Optimization
183
+
184
+ Why are these times so consistent? GitAI does not just dump raw data into the LLM. It includes a custom pre-processing pipeline that strips out compiler noise, binary files, white spaces, and structural brackets before sending the payload.
185
+
186
+ * **Linear vs. Deductive Processing:** Testing proved that sending a complete, clean code block up to 2500 characters is significantly faster than truncating it too early. By providing the model with full, clean context, the LLM processes the data linearly instead of wasting CPU cycles trying to "guess" missing code structures. This balance cuts down processing overhead by up to 30 seconds on older machines while boosting commit accuracy to a staggering **98%**.
187
+
188
+ ## Dependencies
189
+
190
+ | Package | Purpose |
191
+ |---------|---------|
192
+ | llama-cpp-python | Run the local AI model as an HTTP server |
193
+ | httpx | Download the model and communicate with the daemon |
194
+ | psutil | Stop the background daemon (`gitai out`) |
195
+ | colorama | Handle cross-platform terminal text colorization and visual hierarchy |
196
+
197
+ ---
198
+
199
+ ## License
200
+
201
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
202
+
203
+ ---
204
+
205
+ *Developed by [Pablo Salinas](https://github.com/PabloSalinasDev)* - PyBloSoft © 2026
File without changes
@@ -0,0 +1,129 @@
1
+ import os
2
+ import threading
3
+ import time
4
+ import sys
5
+ import subprocess
6
+ from pathlib import Path
7
+ from colorama import init, Fore, Style
8
+
9
+ init(autoreset=True)
10
+
11
+
12
+ MODEL_DIR = Path(os.environ.get("LOCALAPPDATA", ".")) / "gitai" / "models"
13
+ MODEL_FILENAME = "Qwen2.5.1-Coder-7B-Instruct-Q4_K_M.gguf"
14
+ MODEL_PATH = MODEL_DIR / MODEL_FILENAME
15
+ MODEL_URL = "https://huggingface.co/bartowski/Qwen2.5.1-Coder-7B-Instruct-GGUF/resolve/main/Qwen2.5.1-Coder-7B-Instruct-Q4_K_M.gguf?download=true"
16
+ PORT = 8089
17
+
18
+ def get_secure_env():
19
+ env = os.environ.copy()
20
+ env["LC_ALL"] = "C.UTF-8"
21
+ env["LANG"] = "C.UTF-8"
22
+ return env
23
+
24
+ def model_exists():
25
+ return MODEL_PATH.exists() and MODEL_PATH.stat().st_size > 100_000_000
26
+
27
+ def download_model(on_progress, on_done, on_error):
28
+ import httpx
29
+ def run():
30
+ try:
31
+ MODEL_DIR.mkdir(parents=True, exist_ok=True)
32
+ tmp_path = MODEL_PATH.with_suffix(".tmp")
33
+
34
+ with httpx.stream("GET", MODEL_URL, follow_redirects=True, timeout=None) as r:
35
+ r.raise_for_status()
36
+ total = int(r.headers.get("content-length", 0))
37
+ downloaded = 0
38
+
39
+ with open(tmp_path, "wb") as f:
40
+ for chunk in r.iter_bytes(chunk_size=1024 * 256):
41
+ f.write(chunk)
42
+ downloaded += len(chunk)
43
+ if total:
44
+ pct = downloaded / total
45
+ d_gb = downloaded / 1_073_741_824
46
+ t_gb = total / 1_073_741_824
47
+ on_progress(pct, d_gb, t_gb)
48
+
49
+ tmp_path.rename(MODEL_PATH)
50
+ on_done()
51
+
52
+ except Exception as e:
53
+ on_error(str(e))
54
+
55
+ threading.Thread(target=run, daemon=True).start()
56
+
57
+ def ensure_model():
58
+ if model_exists():
59
+ return
60
+
61
+ print(Fore.CYAN + "┌─────────────────────────────────────────────┐")
62
+ print(Fore.CYAN + "│ GitAI - First run: downloading AI model │")
63
+ print(Fore.CYAN + "│ AI Model Setup - one time only │")
64
+ print(Fore.CYAN + "└─────────────────────────────────────────────┘\n")
65
+
66
+ done_flag = {"done": False, "error": None}
67
+
68
+ def on_progress(pct, d_gb, t_gb):
69
+ bar_len = 30
70
+ filled = int(bar_len * pct)
71
+ bar = Fore.YELLOW + "█" * filled + Style.DIM + "░" * (bar_len - filled)
72
+ print(Fore.YELLOW + f"\r [{bar}" + Style.RESET_ALL + Fore.YELLOW + f"] {pct*100:.1f}% {d_gb:.2f}/{t_gb:.2f} GB", end="", flush=True)
73
+
74
+ def on_done():
75
+ done_flag["done"] = True
76
+
77
+ def on_error(e):
78
+ done_flag["error"] = e
79
+
80
+ download_model(on_progress, on_done, on_error)
81
+
82
+ while not done_flag["done"] and not done_flag["error"]:
83
+ time.sleep(0.5)
84
+
85
+ if done_flag["error"]:
86
+ print(Fore.RED + f"\n\n Error downloading model: {done_flag['error']}")
87
+ sys.exit(1)
88
+
89
+ print(Fore.GREEN + "\n\n Model downloaded successfully.\n")
90
+
91
+ def get_repo_language(force_ask=False):
92
+ """
93
+ Checks if the language configuration exists for this repository.
94
+ If it doesn't exist or force_ask is True, it asks the user and saves it.
95
+ """
96
+ if not force_ask:
97
+ result = subprocess.run(
98
+ ["git", "config", "--get", "gitai.lang"],
99
+ capture_output=True,
100
+ text=True,
101
+ check=False,
102
+ encoding="utf-8",
103
+ errors="replace",
104
+ env=get_secure_env()
105
+ )
106
+ stored_lang = result.stdout.strip().lower()
107
+ if stored_lang in ["es", "en"]:
108
+ return stored_lang
109
+
110
+ print(Fore.CYAN + "\n [gitai] Language configuration for this repository:")
111
+ while True:
112
+ choice = input(Fore.CYAN + " [s] Spanish [e] English → ").strip().lower()
113
+ if choice == "s":
114
+ lang = "es"
115
+ break
116
+ elif choice == "e":
117
+ lang = "en"
118
+ break
119
+ else:
120
+ print(Fore.RED + " Invalid option. Please select 's' or 'e'.")
121
+
122
+ subprocess.run(
123
+ ["git", "config", "gitai.lang", lang],
124
+ encoding="utf-8",
125
+ check=False,
126
+ env=get_secure_env()
127
+ )
128
+ print(Fore.GREEN + f" Language saved as '{lang}' in the Git configuration of this project.\n")
129
+ return lang