gac 1.0.0__py3-none-any.whl → 1.0.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/__version__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Version information for gac package."""
2
2
 
3
- __version__ = "1.0.0"
3
+ __version__ = "1.0.1"
gac/ai.py CHANGED
@@ -5,9 +5,11 @@ It consolidates all AI-related functionality including token counting and commit
5
5
  """
6
6
 
7
7
  import logging
8
+ import os
8
9
  from functools import lru_cache
9
10
  from typing import Any
10
11
 
12
+ import httpx
11
13
  import tiktoken
12
14
 
13
15
  from gac.ai_providers import (
@@ -30,19 +32,10 @@ def count_tokens(content: str | list[dict[str, str]] | dict[str, Any], model: st
30
32
  return 0
31
33
 
32
34
  if model.startswith("anthropic"):
33
- import anthropic
34
-
35
- try:
36
- client = anthropic.Anthropic()
37
-
38
- # Use the messages.count_tokens API for accurate counting
39
- model_name = model.split(":", 1)[1] if ":" in model else "claude-3-5-haiku-latest"
40
- response = client.messages.count_tokens(model=model_name, messages=[{"role": "user", "content": text}])
41
-
42
- return response.input_tokens
43
- except Exception:
44
- # Fallback to simple estimation for Anthropic models
45
- return len(text) // 4
35
+ anthropic_tokens = anthropic_count_tokens(text, model)
36
+ if anthropic_tokens is not None:
37
+ return anthropic_tokens
38
+ return len(text) // 4
46
39
 
47
40
  try:
48
41
  encoding = get_encoding(model)
@@ -52,6 +45,60 @@ def count_tokens(content: str | list[dict[str, str]] | dict[str, Any], model: st
52
45
  return len(text) // 4
53
46
 
54
47
 
48
+ def anthropic_count_tokens(text: str, model: str) -> int | None:
49
+ """Call Anthropic's token count endpoint and return the token usage.
50
+
51
+ Returns the token count when successful, otherwise ``None`` so callers can
52
+ fall back to a heuristic estimate.
53
+ """
54
+ api_key = os.getenv("ANTHROPIC_API_KEY")
55
+ if not api_key:
56
+ logger.debug("ANTHROPIC_API_KEY not set; using heuristic token estimation for Anthropic model")
57
+ return None
58
+
59
+ model_name = model.split(":", 1)[1] if ":" in model else "claude-3-5-haiku-latest"
60
+ headers = {
61
+ "Content-Type": "application/json",
62
+ "x-api-key": api_key,
63
+ "anthropic-version": "2023-06-01",
64
+ }
65
+ payload = {
66
+ "model": model_name,
67
+ "messages": [
68
+ {
69
+ "role": "user",
70
+ "content": [
71
+ {
72
+ "type": "text",
73
+ "text": text,
74
+ }
75
+ ],
76
+ }
77
+ ],
78
+ }
79
+
80
+ try:
81
+ response = httpx.post(
82
+ "https://api.anthropic.com/v1/messages/count_tokens",
83
+ headers=headers,
84
+ json=payload,
85
+ timeout=30.0,
86
+ )
87
+ response.raise_for_status()
88
+ data = response.json()
89
+
90
+ if "input_tokens" in data:
91
+ return data["input_tokens"]
92
+ if "usage" in data and "input_tokens" in data["usage"]:
93
+ return data["usage"]["input_tokens"]
94
+
95
+ logger.warning("Unexpected response format from Anthropic token count API: %s", data)
96
+ except Exception as exc:
97
+ logger.warning("Failed to retrieve Anthropic token count via HTTP: %s", exc)
98
+
99
+ return None
100
+
101
+
55
102
  def extract_text_content(content: str | list[dict[str, str]] | dict[str, Any]) -> str:
56
103
  """Extract text content from various input formats."""
57
104
  if isinstance(content, str):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gac
3
- Version: 1.0.0
3
+ Version: 1.0.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
@@ -1,6 +1,6 @@
1
1
  gac/__init__.py,sha256=T3KAW47ZmvB5AozG_uL92ryBYgp-2LNEztBaxaY3dJE,674
2
- gac/__version__.py,sha256=dFDGI6kSyoMIM0lfv_qWhBcmDf6A-bxqO14NKF-1bbg,66
3
- gac/ai.py,sha256=7rqXXXXNZiQe1vsPNoFU-jnLXfbnTTmnGKUYBZXpCFI,4928
2
+ gac/__version__.py,sha256=8Yc4NMnplKKb2pLEFCgKeKRVX9Q-31V40n444l7Ao5M,66
3
+ gac/ai.py,sha256=E0vfkWyqYvNJFAbOYvHG-tnwcQakAYm34oHMbKM5GIk,6267
4
4
  gac/ai_providers.py,sha256=QiVSspn0cauxl7m1Chn6nw1kAO1ByAuPiQqZWyZZCys,13210
5
5
  gac/cli.py,sha256=eQS8S7v6p0CfN9wtr239ujYGTi9rKl-KV7STX2U-C3w,4581
6
6
  gac/config.py,sha256=wSgEDjtis7Vk1pv5VPvYmJyD9-tymDS6GiUHjnCMbIM,1486
@@ -14,8 +14,8 @@ gac/main.py,sha256=WI7mxIbL05neQr1VfoopOeZKIonwpwFeZCt_4VFewPY,11987
14
14
  gac/preprocess.py,sha256=4igtZ9OTHgTpqwlJmbcGaqzmdD0HHCZJwsZ9eG118Gk,15360
15
15
  gac/prompt.py,sha256=_fv24XU3DZE_S72vcdUYnNkmy-_KXnr1Vlc-9okop7E,17263
16
16
  gac/utils.py,sha256=W3ladtmsH01MNLdckQYTzYrYbTGEdzCKI36he9C-y_E,3945
17
- gac-1.0.0.dist-info/METADATA,sha256=OOLz0xmLbHsSAgfKa0830-zIGhwT_9VMqlI7b72cV6Y,8351
18
- gac-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
19
- gac-1.0.0.dist-info/entry_points.txt,sha256=tdjN-XMmcWfL92swuRAjT62bFLOAwk9bTMRLGP5Z4aI,36
20
- gac-1.0.0.dist-info/licenses/LICENSE,sha256=vOab37NouL1PNs5BswnPayrMCqaN2sqLfMQfqPDrpZg,1103
21
- gac-1.0.0.dist-info/RECORD,,
17
+ gac-1.0.1.dist-info/METADATA,sha256=iEfp3b1Mx12iwon4aD6QDE8foNYrn-dN9yCmwhuKQTU,8351
18
+ gac-1.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
19
+ gac-1.0.1.dist-info/entry_points.txt,sha256=tdjN-XMmcWfL92swuRAjT62bFLOAwk9bTMRLGP5Z4aI,36
20
+ gac-1.0.1.dist-info/licenses/LICENSE,sha256=vOab37NouL1PNs5BswnPayrMCqaN2sqLfMQfqPDrpZg,1103
21
+ gac-1.0.1.dist-info/RECORD,,
File without changes