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.

@@ -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
- def generate(
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
- if isinstance(prompt, tuple):
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
- return _make_request_with_retry(
57
- url="https://openrouter.ai/api/v1/chat/completions",
58
- headers=headers,
59
- payload=payload,
60
- provider_name=f"OpenRouter {model}",
61
- max_retries=max_retries,
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
- error_type = _classify_error(str(last_error))
123
- raise AIError(
124
- f"Failed to generate commit message after {max_retries} attempts: {last_error}", error_type=error_type
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.0
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,,
@@ -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