gac 1.1.0__py3-none-any.whl → 1.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of gac might be problematic. Click here for more details.
- gac/__init__.py +6 -6
- gac/__version__.py +1 -1
- gac/ai.py +43 -34
- gac/ai_utils.py +113 -62
- gac/errors.py +5 -0
- gac/providers/__init__.py +17 -1
- gac/providers/anthropic.py +32 -131
- gac/providers/cerebras.py +19 -124
- gac/providers/groq.py +43 -119
- gac/providers/ollama.py +27 -127
- gac/providers/openai.py +18 -123
- gac/providers/openrouter.py +19 -98
- {gac-1.1.0.dist-info → gac-1.2.1.dist-info}/METADATA +1 -1
- gac-1.2.1.dist-info/RECORD +28 -0
- gac-1.1.0.dist-info/RECORD +0 -28
- {gac-1.1.0.dist-info → gac-1.2.1.dist-info}/WHEEL +0 -0
- {gac-1.1.0.dist-info → gac-1.2.1.dist-info}/entry_points.txt +0 -0
- {gac-1.1.0.dist-info → gac-1.2.1.dist-info}/licenses/LICENSE +0 -0
gac/providers/openrouter.py
CHANGED
|
@@ -1,50 +1,25 @@
|
|
|
1
1
|
"""OpenRouter API provider for gac."""
|
|
2
2
|
|
|
3
|
-
import logging
|
|
4
3
|
import os
|
|
5
|
-
import time
|
|
6
4
|
|
|
7
5
|
import httpx
|
|
8
|
-
from halo import Halo
|
|
9
6
|
|
|
10
|
-
from gac.ai_utils import _classify_error
|
|
11
|
-
from gac.constants import EnvDefaults
|
|
12
7
|
from gac.errors import AIError
|
|
13
8
|
|
|
14
|
-
logger = logging.getLogger(__name__)
|
|
15
9
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
model: str,
|
|
19
|
-
prompt: str | tuple[str, str],
|
|
20
|
-
temperature: float = EnvDefaults.TEMPERATURE,
|
|
21
|
-
max_tokens: int = EnvDefaults.MAX_OUTPUT_TOKENS,
|
|
22
|
-
max_retries: int = EnvDefaults.MAX_RETRIES,
|
|
23
|
-
quiet: bool = False,
|
|
24
|
-
) -> str:
|
|
25
|
-
"""Generate commit message using OpenRouter API with retry logic."""
|
|
10
|
+
def call_openrouter_api(model: str, messages: list[dict], temperature: float, max_tokens: int) -> str:
|
|
11
|
+
"""Call OpenRouter API directly."""
|
|
26
12
|
api_key = os.getenv("OPENROUTER_API_KEY")
|
|
27
13
|
if not api_key:
|
|
28
14
|
raise AIError.model_error("OPENROUTER_API_KEY environment variable not set")
|
|
29
15
|
|
|
30
|
-
|
|
31
|
-
system_prompt, user_prompt = prompt
|
|
32
|
-
messages = [{"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}]
|
|
33
|
-
else:
|
|
34
|
-
messages = [{"role": "user", "content": prompt}]
|
|
35
|
-
|
|
36
|
-
payload = {
|
|
37
|
-
"model": model,
|
|
38
|
-
"messages": messages,
|
|
39
|
-
"temperature": temperature,
|
|
40
|
-
"max_tokens": max_tokens,
|
|
41
|
-
}
|
|
42
|
-
|
|
16
|
+
url = "https://openrouter.ai/api/v1/chat/completions"
|
|
43
17
|
headers = {
|
|
44
18
|
"Content-Type": "application/json",
|
|
45
19
|
"Authorization": f"Bearer {api_key}",
|
|
46
20
|
}
|
|
47
21
|
|
|
22
|
+
# Add optional headers if environment variables are set
|
|
48
23
|
site_url = os.getenv("OPENROUTER_SITE_URL")
|
|
49
24
|
if site_url:
|
|
50
25
|
headers["HTTP-Referer"] = site_url
|
|
@@ -53,73 +28,19 @@ def generate(
|
|
|
53
28
|
if site_name:
|
|
54
29
|
headers["X-Title"] = site_name
|
|
55
30
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
quiet=quiet,
|
|
63
|
-
response_parser=lambda r: r["choices"][0]["message"]["content"],
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def _make_request_with_retry(
|
|
68
|
-
url: str,
|
|
69
|
-
headers: dict,
|
|
70
|
-
payload: dict,
|
|
71
|
-
provider_name: str,
|
|
72
|
-
max_retries: int,
|
|
73
|
-
quiet: bool,
|
|
74
|
-
response_parser: callable,
|
|
75
|
-
) -> str:
|
|
76
|
-
"""Make HTTP request with retry logic and common error handling."""
|
|
77
|
-
if quiet:
|
|
78
|
-
spinner = None
|
|
79
|
-
else:
|
|
80
|
-
spinner = Halo(text=f"Generating commit message with {provider_name}...", spinner="dots")
|
|
81
|
-
spinner.start()
|
|
82
|
-
|
|
83
|
-
last_error = None
|
|
84
|
-
retry_count = 0
|
|
85
|
-
|
|
86
|
-
while retry_count < max_retries:
|
|
87
|
-
try:
|
|
88
|
-
logger.debug(f"Trying with {provider_name} (attempt {retry_count + 1}/{max_retries})")
|
|
89
|
-
|
|
90
|
-
with httpx.Client(timeout=30.0) as client:
|
|
91
|
-
response = client.post(url, headers=headers, json=payload)
|
|
92
|
-
response.raise_for_status()
|
|
93
|
-
|
|
94
|
-
response_data = response.json()
|
|
95
|
-
message = response_parser(response_data)
|
|
96
|
-
|
|
97
|
-
if spinner:
|
|
98
|
-
spinner.succeed(f"Generated commit message with {provider_name}")
|
|
99
|
-
|
|
100
|
-
return message
|
|
101
|
-
|
|
102
|
-
except Exception as e:
|
|
103
|
-
last_error = e
|
|
104
|
-
retry_count += 1
|
|
105
|
-
|
|
106
|
-
if retry_count == max_retries:
|
|
107
|
-
logger.warning(f"Error generating commit message: {e}. Giving up.")
|
|
108
|
-
break
|
|
109
|
-
|
|
110
|
-
wait_time = 2**retry_count
|
|
111
|
-
logger.warning(f"Error generating commit message: {e}. Retrying in {wait_time}s...")
|
|
112
|
-
if spinner:
|
|
113
|
-
for i in range(wait_time, 0, -1):
|
|
114
|
-
spinner.text = f"Retry {retry_count}/{max_retries} in {i}s..."
|
|
115
|
-
time.sleep(1)
|
|
116
|
-
else:
|
|
117
|
-
time.sleep(wait_time)
|
|
118
|
-
|
|
119
|
-
if spinner:
|
|
120
|
-
spinner.fail(f"Failed to generate commit message with {provider_name}")
|
|
31
|
+
data = {
|
|
32
|
+
"model": model,
|
|
33
|
+
"messages": messages,
|
|
34
|
+
"temperature": temperature,
|
|
35
|
+
"max_tokens": max_tokens,
|
|
36
|
+
}
|
|
121
37
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
38
|
+
try:
|
|
39
|
+
response = httpx.post(url, headers=headers, json=data, timeout=120)
|
|
40
|
+
response.raise_for_status()
|
|
41
|
+
response_data = response.json()
|
|
42
|
+
return response_data["choices"][0]["message"]["content"]
|
|
43
|
+
except httpx.HTTPStatusError as e:
|
|
44
|
+
raise AIError.model_error(f"OpenRouter API error: {e.response.status_code} - {e.response.text}") from e
|
|
45
|
+
except Exception as e:
|
|
46
|
+
raise AIError.model_error(f"Error calling OpenRouter API: {str(e)}") from e
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gac
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: AI-powered Git commit message generator with multi-provider support
|
|
5
5
|
Project-URL: Homepage, https://github.com/cellwebb/gac
|
|
6
6
|
Project-URL: Documentation, https://github.com/cellwebb/gac#readme
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
gac/__init__.py,sha256=HFWgSVNbTAFhgetCRWI1WrtyE7zC7IHvoBOrfDGUurM,989
|
|
2
|
+
gac/__version__.py,sha256=mlHECiUCezS8zokbb1QH5XRF5CbT1gnkLsHOUqsJMpQ,66
|
|
3
|
+
gac/ai.py,sha256=iW7DqVoWGaHJeUWhkcYgFxJZHEkvNMcKgnEFQiBT_Dg,3090
|
|
4
|
+
gac/ai_utils.py,sha256=4qr1Jpm89ND5avqWQoQIjyc-zS-CPLoODjlhI44l8M8,7079
|
|
5
|
+
gac/cli.py,sha256=eQS8S7v6p0CfN9wtr239ujYGTi9rKl-KV7STX2U-C3w,4581
|
|
6
|
+
gac/config.py,sha256=wSgEDjtis7Vk1pv5VPvYmJyD9-tymDS6GiUHjnCMbIM,1486
|
|
7
|
+
gac/config_cli.py,sha256=v9nFHZO1RvK9fzHyuUS6SG-BCLHMsdOMDwWamBhVVh4,1608
|
|
8
|
+
gac/constants.py,sha256=MAxdASGncfZY1TdKGdhJZ0wvTBEU3gTN6KEdw8n3Bd8,4844
|
|
9
|
+
gac/diff_cli.py,sha256=wnVQ9OFGnM0d2Pj9WVjWbo0jxqIuRHVAwmb8wU9Pa3E,5676
|
|
10
|
+
gac/errors.py,sha256=kwKxBhBpdgESRftUdN8RBiGDKE7E_H7nFN5-JVNyZE4,7578
|
|
11
|
+
gac/git.py,sha256=MS2m4fv8h4mau1djFG1aje9NXTmkGsjPO9w18LqNGX0,6031
|
|
12
|
+
gac/init_cli.py,sha256=e4z9-4NhoUn2DUyApIru8JR-W7HuNq2VeeXkR9aXHLo,1868
|
|
13
|
+
gac/main.py,sha256=POay7l6ihm3oF9ajGWx9cA40Pu-NVz5x_OzQOYPDoX8,12011
|
|
14
|
+
gac/preprocess.py,sha256=krrLPHsccYMdn_YAtUrppBJIoRgevxGWusDwhE40LEo,15366
|
|
15
|
+
gac/prompt.py,sha256=_fv24XU3DZE_S72vcdUYnNkmy-_KXnr1Vlc-9okop7E,17263
|
|
16
|
+
gac/utils.py,sha256=W3ladtmsH01MNLdckQYTzYrYbTGEdzCKI36he9C-y_E,3945
|
|
17
|
+
gac/providers/__init__.py,sha256=iGwZmV-cFqL3AeFE0vc6KpHwm-RLWcVSU17c7IvJg2s,456
|
|
18
|
+
gac/providers/anthropic.py,sha256=esf6pq6nRdqD0mpKz_IQNXmXe5WnkoSA2b1isrrRB4o,1514
|
|
19
|
+
gac/providers/cerebras.py,sha256=eE9lAjEzrATIo941vv97I2DSmpnXYBCJ9HkVIb-6Whg,1130
|
|
20
|
+
gac/providers/groq.py,sha256=Z-j-RKrRGV7evSWxTyKKnPff1Mn5YmYZxitqWVlwadE,2452
|
|
21
|
+
gac/providers/ollama.py,sha256=Bp94DvortQssDhekuNdJ7fKLeWpWASYXSssJNCuGszg,1383
|
|
22
|
+
gac/providers/openai.py,sha256=1l-Wu7ETXXaJ7cNB3OD5ivf4_72iIEP9bPFMQst8JWI,1109
|
|
23
|
+
gac/providers/openrouter.py,sha256=Vs0MXfv9KCldfEUD2roTwcXqs89tgE3ndNqRKoqdJQs,1473
|
|
24
|
+
gac-1.2.1.dist-info/METADATA,sha256=RWaYfOmCltyXsiO0a3Fuz1Qy-0Msr7tAWySzG2OdXsw,8558
|
|
25
|
+
gac-1.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
26
|
+
gac-1.2.1.dist-info/entry_points.txt,sha256=tdjN-XMmcWfL92swuRAjT62bFLOAwk9bTMRLGP5Z4aI,36
|
|
27
|
+
gac-1.2.1.dist-info/licenses/LICENSE,sha256=vOab37NouL1PNs5BswnPayrMCqaN2sqLfMQfqPDrpZg,1103
|
|
28
|
+
gac-1.2.1.dist-info/RECORD,,
|
gac-1.1.0.dist-info/RECORD
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
gac/__init__.py,sha256=-knZC1oRylbJUv5uGk3fP_dHaaLHG76duAEWxLUi1eg,940
|
|
2
|
-
gac/__version__.py,sha256=JSz2jRyqqtKTmDkhJ8NI5pr2e0rhFqSSkokXslLdc2M,66
|
|
3
|
-
gac/ai.py,sha256=-Wd9cr5yK-UvR14AHvBeHrpa28KXu0bYZjJS02U-q90,3419
|
|
4
|
-
gac/ai_utils.py,sha256=DFiM0Wzp-kremo33_i5SEYpms7tE13ipKLCCr_-AZPU,4327
|
|
5
|
-
gac/cli.py,sha256=eQS8S7v6p0CfN9wtr239ujYGTi9rKl-KV7STX2U-C3w,4581
|
|
6
|
-
gac/config.py,sha256=wSgEDjtis7Vk1pv5VPvYmJyD9-tymDS6GiUHjnCMbIM,1486
|
|
7
|
-
gac/config_cli.py,sha256=v9nFHZO1RvK9fzHyuUS6SG-BCLHMsdOMDwWamBhVVh4,1608
|
|
8
|
-
gac/constants.py,sha256=MAxdASGncfZY1TdKGdhJZ0wvTBEU3gTN6KEdw8n3Bd8,4844
|
|
9
|
-
gac/diff_cli.py,sha256=wnVQ9OFGnM0d2Pj9WVjWbo0jxqIuRHVAwmb8wU9Pa3E,5676
|
|
10
|
-
gac/errors.py,sha256=3vIRMQ2QF3sP9_rPfXAFuu5ZSjIVX4FxM-FAuiR8N-8,7416
|
|
11
|
-
gac/git.py,sha256=MS2m4fv8h4mau1djFG1aje9NXTmkGsjPO9w18LqNGX0,6031
|
|
12
|
-
gac/init_cli.py,sha256=e4z9-4NhoUn2DUyApIru8JR-W7HuNq2VeeXkR9aXHLo,1868
|
|
13
|
-
gac/main.py,sha256=POay7l6ihm3oF9ajGWx9cA40Pu-NVz5x_OzQOYPDoX8,12011
|
|
14
|
-
gac/preprocess.py,sha256=krrLPHsccYMdn_YAtUrppBJIoRgevxGWusDwhE40LEo,15366
|
|
15
|
-
gac/prompt.py,sha256=_fv24XU3DZE_S72vcdUYnNkmy-_KXnr1Vlc-9okop7E,17263
|
|
16
|
-
gac/utils.py,sha256=W3ladtmsH01MNLdckQYTzYrYbTGEdzCKI36he9C-y_E,3945
|
|
17
|
-
gac/providers/__init__.py,sha256=_JawPCV_ZCtI18bBqVCbQkkbLetSQqOBcj2b19KRuX0,38
|
|
18
|
-
gac/providers/anthropic.py,sha256=v0JApD6dNfIbxBoFbpf4GBWc4PsVPgcEcw1GDEWhoeM,4382
|
|
19
|
-
gac/providers/cerebras.py,sha256=rWtndVj9q1w-EIfLyP4NJ10GFPnlfiu43ZminTdWP1s,4166
|
|
20
|
-
gac/providers/groq.py,sha256=K7hrHaYfGn25hnDedR6FBEOqb0r0Y65zQRYso5w3xGE,4156
|
|
21
|
-
gac/providers/ollama.py,sha256=qzX4qMsQeZUh8oPOWFIszhsvgioSnoLi82wO8G13pOI,4139
|
|
22
|
-
gac/providers/openai.py,sha256=VKH7SQE6O4UB1c15KXIBL5UP1Fj3Ed4XQDrqENEPmBo,4150
|
|
23
|
-
gac/providers/openrouter.py,sha256=vU4zIwtnyz9hjWokJwORwX3bZjYtF2MWqz8xxE-srsA,3753
|
|
24
|
-
gac-1.1.0.dist-info/METADATA,sha256=VImMQAbgQT23S1czOiINsmy4tnloF8MRcb9_TSvasrI,8558
|
|
25
|
-
gac-1.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
26
|
-
gac-1.1.0.dist-info/entry_points.txt,sha256=tdjN-XMmcWfL92swuRAjT62bFLOAwk9bTMRLGP5Z4aI,36
|
|
27
|
-
gac-1.1.0.dist-info/licenses/LICENSE,sha256=vOab37NouL1PNs5BswnPayrMCqaN2sqLfMQfqPDrpZg,1103
|
|
28
|
-
gac-1.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|