gac 3.6.0__py3-none-any.whl → 3.8.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.
- gac/__version__.py +1 -1
- gac/ai_utils.py +47 -0
- gac/auth_cli.py +181 -36
- gac/cli.py +13 -0
- gac/config.py +54 -0
- gac/constants.py +7 -0
- gac/main.py +53 -11
- gac/model_cli.py +65 -10
- gac/oauth/__init__.py +26 -0
- gac/oauth/claude_code.py +87 -20
- gac/oauth/qwen_oauth.py +323 -0
- gac/oauth/token_store.py +81 -0
- gac/prompt.py +16 -4
- gac/providers/__init__.py +3 -0
- gac/providers/anthropic.py +11 -1
- gac/providers/azure_openai.py +5 -1
- gac/providers/cerebras.py +11 -1
- gac/providers/chutes.py +11 -1
- gac/providers/claude_code.py +11 -1
- gac/providers/custom_anthropic.py +5 -1
- gac/providers/custom_openai.py +5 -1
- gac/providers/deepseek.py +11 -1
- gac/providers/fireworks.py +11 -1
- gac/providers/gemini.py +11 -1
- gac/providers/groq.py +5 -1
- gac/providers/kimi_coding.py +5 -1
- gac/providers/lmstudio.py +12 -1
- gac/providers/minimax.py +11 -1
- gac/providers/mistral.py +11 -1
- gac/providers/moonshot.py +11 -1
- gac/providers/ollama.py +11 -1
- gac/providers/openai.py +11 -1
- gac/providers/openrouter.py +11 -1
- gac/providers/qwen.py +76 -0
- gac/providers/replicate.py +14 -2
- gac/providers/streamlake.py +11 -1
- gac/providers/synthetic.py +11 -1
- gac/providers/together.py +11 -1
- gac/providers/zai.py +11 -1
- gac/utils.py +30 -1
- gac/workflow_utils.py +3 -8
- {gac-3.6.0.dist-info → gac-3.8.1.dist-info}/METADATA +6 -4
- gac-3.8.1.dist-info/RECORD +56 -0
- gac-3.6.0.dist-info/RECORD +0 -53
- {gac-3.6.0.dist-info → gac-3.8.1.dist-info}/WHEEL +0 -0
- {gac-3.6.0.dist-info → gac-3.8.1.dist-info}/entry_points.txt +0 -0
- {gac-3.6.0.dist-info → gac-3.8.1.dist-info}/licenses/LICENSE +0 -0
gac/providers/moonshot.py
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"""Moonshot AI provider for gac."""
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
6
7
|
|
|
8
|
+
from gac.constants import ProviderDefaults
|
|
7
9
|
from gac.errors import AIError
|
|
10
|
+
from gac.utils import get_ssl_verify
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
def call_moonshot_api(model: str, messages: list[dict], temperature: float, max_tokens: int) -> str:
|
|
@@ -18,8 +23,12 @@ def call_moonshot_api(model: str, messages: list[dict], temperature: float, max_
|
|
|
18
23
|
|
|
19
24
|
data = {"model": model, "messages": messages, "temperature": temperature, "max_tokens": max_tokens}
|
|
20
25
|
|
|
26
|
+
logger.debug(f"Calling Moonshot AI API with model={model}")
|
|
27
|
+
|
|
21
28
|
try:
|
|
22
|
-
response = httpx.post(
|
|
29
|
+
response = httpx.post(
|
|
30
|
+
url, headers=headers, json=data, timeout=ProviderDefaults.HTTP_TIMEOUT, verify=get_ssl_verify()
|
|
31
|
+
)
|
|
23
32
|
response.raise_for_status()
|
|
24
33
|
response_data = response.json()
|
|
25
34
|
content = response_data["choices"][0]["message"]["content"]
|
|
@@ -27,6 +36,7 @@ def call_moonshot_api(model: str, messages: list[dict], temperature: float, max_
|
|
|
27
36
|
raise AIError.model_error("Moonshot AI API returned null content")
|
|
28
37
|
if content == "":
|
|
29
38
|
raise AIError.model_error("Moonshot AI API returned empty content")
|
|
39
|
+
logger.debug("Moonshot AI API response received successfully")
|
|
30
40
|
return content
|
|
31
41
|
except httpx.HTTPStatusError as e:
|
|
32
42
|
if e.response.status_code == 429:
|
gac/providers/ollama.py
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"""Ollama AI provider implementation."""
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
6
7
|
|
|
8
|
+
from gac.constants import ProviderDefaults
|
|
7
9
|
from gac.errors import AIError
|
|
10
|
+
from gac.utils import get_ssl_verify
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
def call_ollama_api(model: str, messages: list[dict], temperature: float, max_tokens: int) -> str:
|
|
@@ -18,8 +23,12 @@ def call_ollama_api(model: str, messages: list[dict], temperature: float, max_to
|
|
|
18
23
|
if api_key:
|
|
19
24
|
headers["Authorization"] = f"Bearer {api_key}"
|
|
20
25
|
|
|
26
|
+
logger.debug(f"Calling Ollama API with model={model}")
|
|
27
|
+
|
|
21
28
|
try:
|
|
22
|
-
response = httpx.post(
|
|
29
|
+
response = httpx.post(
|
|
30
|
+
url, headers=headers, json=data, timeout=ProviderDefaults.HTTP_TIMEOUT, verify=get_ssl_verify()
|
|
31
|
+
)
|
|
23
32
|
response.raise_for_status()
|
|
24
33
|
response_data = response.json()
|
|
25
34
|
|
|
@@ -37,6 +46,7 @@ def call_ollama_api(model: str, messages: list[dict], temperature: float, max_to
|
|
|
37
46
|
raise AIError.model_error("Ollama API returned null content")
|
|
38
47
|
if content == "":
|
|
39
48
|
raise AIError.model_error("Ollama API returned empty content")
|
|
49
|
+
logger.debug("Ollama API response received successfully")
|
|
40
50
|
return content
|
|
41
51
|
except httpx.ConnectError as e:
|
|
42
52
|
raise AIError.connection_error(f"Ollama connection failed. Make sure Ollama is running: {str(e)}") from e
|
gac/providers/openai.py
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"""OpenAI API provider for gac."""
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
6
7
|
|
|
8
|
+
from gac.constants import ProviderDefaults
|
|
7
9
|
from gac.errors import AIError
|
|
10
|
+
from gac.utils import get_ssl_verify
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
def call_openai_api(model: str, messages: list[dict], temperature: float, max_tokens: int) -> str:
|
|
@@ -18,8 +23,12 @@ def call_openai_api(model: str, messages: list[dict], temperature: float, max_to
|
|
|
18
23
|
|
|
19
24
|
data = {"model": model, "messages": messages, "temperature": temperature, "max_completion_tokens": max_tokens}
|
|
20
25
|
|
|
26
|
+
logger.debug(f"Calling OpenAI API with model={model}")
|
|
27
|
+
|
|
21
28
|
try:
|
|
22
|
-
response = httpx.post(
|
|
29
|
+
response = httpx.post(
|
|
30
|
+
url, headers=headers, json=data, timeout=ProviderDefaults.HTTP_TIMEOUT, verify=get_ssl_verify()
|
|
31
|
+
)
|
|
23
32
|
response.raise_for_status()
|
|
24
33
|
response_data = response.json()
|
|
25
34
|
content = response_data["choices"][0]["message"]["content"]
|
|
@@ -27,6 +36,7 @@ def call_openai_api(model: str, messages: list[dict], temperature: float, max_to
|
|
|
27
36
|
raise AIError.model_error("OpenAI API returned null content")
|
|
28
37
|
if content == "":
|
|
29
38
|
raise AIError.model_error("OpenAI API returned empty content")
|
|
39
|
+
logger.debug("OpenAI API response received successfully")
|
|
30
40
|
return content
|
|
31
41
|
except httpx.HTTPStatusError as e:
|
|
32
42
|
if e.response.status_code == 429:
|
gac/providers/openrouter.py
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"""OpenRouter API provider for gac."""
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
6
7
|
|
|
8
|
+
from gac.constants import ProviderDefaults
|
|
7
9
|
from gac.errors import AIError
|
|
10
|
+
from gac.utils import get_ssl_verify
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
def call_openrouter_api(model: str, messages: list[dict], temperature: float, max_tokens: int) -> str:
|
|
@@ -26,8 +31,12 @@ def call_openrouter_api(model: str, messages: list[dict], temperature: float, ma
|
|
|
26
31
|
"max_tokens": max_tokens,
|
|
27
32
|
}
|
|
28
33
|
|
|
34
|
+
logger.debug(f"Calling OpenRouter API with model={model}")
|
|
35
|
+
|
|
29
36
|
try:
|
|
30
|
-
response = httpx.post(
|
|
37
|
+
response = httpx.post(
|
|
38
|
+
url, headers=headers, json=data, timeout=ProviderDefaults.HTTP_TIMEOUT, verify=get_ssl_verify()
|
|
39
|
+
)
|
|
31
40
|
response.raise_for_status()
|
|
32
41
|
response_data = response.json()
|
|
33
42
|
content = response_data["choices"][0]["message"]["content"]
|
|
@@ -35,6 +44,7 @@ def call_openrouter_api(model: str, messages: list[dict], temperature: float, ma
|
|
|
35
44
|
raise AIError.model_error("OpenRouter API returned null content")
|
|
36
45
|
if content == "":
|
|
37
46
|
raise AIError.model_error("OpenRouter API returned empty content")
|
|
47
|
+
logger.debug("OpenRouter API response received successfully")
|
|
38
48
|
return content
|
|
39
49
|
except httpx.HTTPStatusError as e:
|
|
40
50
|
# Handle specific HTTP status codes
|
gac/providers/qwen.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Qwen API provider for gac with OAuth support."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
from gac.constants import ProviderDefaults
|
|
9
|
+
from gac.errors import AIError
|
|
10
|
+
from gac.oauth import QwenOAuthProvider, TokenStore
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
QWEN_API_URL = "https://chat.qwen.ai/api/v1/chat/completions"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_qwen_auth() -> tuple[str, str]:
|
|
18
|
+
"""Get Qwen authentication (API key or OAuth token).
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
Tuple of (token, api_url) for authentication.
|
|
22
|
+
"""
|
|
23
|
+
api_key = os.getenv("QWEN_API_KEY")
|
|
24
|
+
if api_key:
|
|
25
|
+
return api_key, QWEN_API_URL
|
|
26
|
+
|
|
27
|
+
oauth_provider = QwenOAuthProvider(TokenStore())
|
|
28
|
+
token = oauth_provider.get_token()
|
|
29
|
+
if token:
|
|
30
|
+
resource_url = token.get("resource_url")
|
|
31
|
+
if resource_url:
|
|
32
|
+
if not resource_url.startswith(("http://", "https://")):
|
|
33
|
+
resource_url = f"https://{resource_url}"
|
|
34
|
+
if not resource_url.endswith("/chat/completions"):
|
|
35
|
+
resource_url = resource_url.rstrip("/") + "/v1/chat/completions"
|
|
36
|
+
api_url = resource_url
|
|
37
|
+
else:
|
|
38
|
+
api_url = QWEN_API_URL
|
|
39
|
+
return token["access_token"], api_url
|
|
40
|
+
|
|
41
|
+
raise AIError.authentication_error(
|
|
42
|
+
"Qwen authentication not found. Set QWEN_API_KEY or run 'gac auth qwen login' for OAuth."
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def call_qwen_api(model: str, messages: list[dict], temperature: float, max_tokens: int) -> str:
|
|
47
|
+
"""Call Qwen API with OAuth or API key authentication."""
|
|
48
|
+
auth_token, api_url = get_qwen_auth()
|
|
49
|
+
|
|
50
|
+
headers = {"Authorization": f"Bearer {auth_token}", "Content-Type": "application/json"}
|
|
51
|
+
|
|
52
|
+
data = {"model": model, "messages": messages, "temperature": temperature, "max_tokens": max_tokens}
|
|
53
|
+
|
|
54
|
+
logger.debug(f"Calling Qwen API with model={model}")
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
response = httpx.post(api_url, headers=headers, json=data, timeout=ProviderDefaults.HTTP_TIMEOUT)
|
|
58
|
+
response.raise_for_status()
|
|
59
|
+
response_data = response.json()
|
|
60
|
+
content = response_data["choices"][0]["message"]["content"]
|
|
61
|
+
if content is None:
|
|
62
|
+
raise AIError.model_error("Qwen API returned null content")
|
|
63
|
+
if content == "":
|
|
64
|
+
raise AIError.model_error("Qwen API returned empty content")
|
|
65
|
+
logger.debug("Qwen API response received successfully")
|
|
66
|
+
return content
|
|
67
|
+
except httpx.HTTPStatusError as e:
|
|
68
|
+
if e.response.status_code == 401:
|
|
69
|
+
raise AIError.authentication_error(f"Qwen authentication failed: {e.response.text}") from e
|
|
70
|
+
if e.response.status_code == 429:
|
|
71
|
+
raise AIError.rate_limit_error(f"Qwen API rate limit exceeded: {e.response.text}") from e
|
|
72
|
+
raise AIError.model_error(f"Qwen API error: {e.response.status_code} - {e.response.text}") from e
|
|
73
|
+
except httpx.TimeoutException as e:
|
|
74
|
+
raise AIError.timeout_error(f"Qwen API request timed out: {str(e)}") from e
|
|
75
|
+
except Exception as e:
|
|
76
|
+
raise AIError.model_error(f"Error calling Qwen API: {str(e)}") from e
|
gac/providers/replicate.py
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"""Replicate API provider for gac."""
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
6
7
|
|
|
8
|
+
from gac.constants import ProviderDefaults
|
|
7
9
|
from gac.errors import AIError
|
|
10
|
+
from gac.utils import get_ssl_verify
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
def call_replicate_api(model: str, messages: list[dict], temperature: float, max_tokens: int) -> str:
|
|
@@ -50,9 +55,13 @@ def call_replicate_api(model: str, messages: list[dict], temperature: float, max
|
|
|
50
55
|
},
|
|
51
56
|
}
|
|
52
57
|
|
|
58
|
+
logger.debug(f"Calling Replicate API with model={model}")
|
|
59
|
+
|
|
53
60
|
try:
|
|
54
61
|
# Create prediction
|
|
55
|
-
response = httpx.post(
|
|
62
|
+
response = httpx.post(
|
|
63
|
+
url, headers=headers, json=data, timeout=ProviderDefaults.HTTP_TIMEOUT, verify=get_ssl_verify()
|
|
64
|
+
)
|
|
56
65
|
response.raise_for_status()
|
|
57
66
|
prediction_data = response.json()
|
|
58
67
|
|
|
@@ -65,7 +74,9 @@ def call_replicate_api(model: str, messages: list[dict], temperature: float, max
|
|
|
65
74
|
elapsed_time = 0
|
|
66
75
|
|
|
67
76
|
while elapsed_time < max_wait_time:
|
|
68
|
-
get_response = httpx.get(
|
|
77
|
+
get_response = httpx.get(
|
|
78
|
+
get_url, headers=headers, timeout=ProviderDefaults.HTTP_TIMEOUT, verify=get_ssl_verify()
|
|
79
|
+
)
|
|
69
80
|
get_response.raise_for_status()
|
|
70
81
|
status_data = get_response.json()
|
|
71
82
|
|
|
@@ -73,6 +84,7 @@ def call_replicate_api(model: str, messages: list[dict], temperature: float, max
|
|
|
73
84
|
content = status_data["output"]
|
|
74
85
|
if not content:
|
|
75
86
|
raise AIError.model_error("Replicate API returned empty content")
|
|
87
|
+
logger.debug("Replicate API response received successfully")
|
|
76
88
|
return content
|
|
77
89
|
elif status_data["status"] == "failed":
|
|
78
90
|
raise AIError.model_error(f"Replicate prediction failed: {status_data.get('error', 'Unknown error')}")
|
gac/providers/streamlake.py
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"""StreamLake (Vanchin) API provider for gac."""
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
6
7
|
|
|
8
|
+
from gac.constants import ProviderDefaults
|
|
7
9
|
from gac.errors import AIError
|
|
10
|
+
from gac.utils import get_ssl_verify
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
def call_streamlake_api(model: str, messages: list[dict], temperature: float, max_tokens: int) -> str:
|
|
@@ -25,8 +30,12 @@ def call_streamlake_api(model: str, messages: list[dict], temperature: float, ma
|
|
|
25
30
|
"max_tokens": max_tokens,
|
|
26
31
|
}
|
|
27
32
|
|
|
33
|
+
logger.debug(f"Calling StreamLake API with model={model}")
|
|
34
|
+
|
|
28
35
|
try:
|
|
29
|
-
response = httpx.post(
|
|
36
|
+
response = httpx.post(
|
|
37
|
+
url, headers=headers, json=data, timeout=ProviderDefaults.HTTP_TIMEOUT, verify=get_ssl_verify()
|
|
38
|
+
)
|
|
30
39
|
response.raise_for_status()
|
|
31
40
|
response_data = response.json()
|
|
32
41
|
choices = response_data.get("choices")
|
|
@@ -40,6 +49,7 @@ def call_streamlake_api(model: str, messages: list[dict], temperature: float, ma
|
|
|
40
49
|
if content == "":
|
|
41
50
|
raise AIError.model_error("StreamLake API returned empty content")
|
|
42
51
|
|
|
52
|
+
logger.debug("StreamLake API response received successfully")
|
|
43
53
|
return content
|
|
44
54
|
except httpx.HTTPStatusError as e:
|
|
45
55
|
if e.response.status_code == 429:
|
gac/providers/synthetic.py
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"""Synthetic.new API provider for gac."""
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
6
7
|
|
|
8
|
+
from gac.constants import ProviderDefaults
|
|
7
9
|
from gac.errors import AIError
|
|
10
|
+
from gac.utils import get_ssl_verify
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
def call_synthetic_api(model: str, messages: list[dict], temperature: float, max_tokens: int) -> str:
|
|
@@ -22,8 +27,12 @@ def call_synthetic_api(model: str, messages: list[dict], temperature: float, max
|
|
|
22
27
|
|
|
23
28
|
data = {"model": model, "messages": messages, "temperature": temperature, "max_completion_tokens": max_tokens}
|
|
24
29
|
|
|
30
|
+
logger.debug(f"Calling Synthetic.new API with model={model}")
|
|
31
|
+
|
|
25
32
|
try:
|
|
26
|
-
response = httpx.post(
|
|
33
|
+
response = httpx.post(
|
|
34
|
+
url, headers=headers, json=data, timeout=ProviderDefaults.HTTP_TIMEOUT, verify=get_ssl_verify()
|
|
35
|
+
)
|
|
27
36
|
response.raise_for_status()
|
|
28
37
|
response_data = response.json()
|
|
29
38
|
content = response_data["choices"][0]["message"]["content"]
|
|
@@ -31,6 +40,7 @@ def call_synthetic_api(model: str, messages: list[dict], temperature: float, max
|
|
|
31
40
|
raise AIError.model_error("Synthetic.new API returned null content")
|
|
32
41
|
if content == "":
|
|
33
42
|
raise AIError.model_error("Synthetic.new API returned empty content")
|
|
43
|
+
logger.debug("Synthetic.new API response received successfully")
|
|
34
44
|
return content
|
|
35
45
|
except httpx.HTTPStatusError as e:
|
|
36
46
|
if e.response.status_code == 429:
|
gac/providers/together.py
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"""Together AI API provider for gac."""
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
6
7
|
|
|
8
|
+
from gac.constants import ProviderDefaults
|
|
7
9
|
from gac.errors import AIError
|
|
10
|
+
from gac.utils import get_ssl_verify
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
def call_together_api(model: str, messages: list[dict], temperature: float, max_tokens: int) -> str:
|
|
@@ -18,8 +23,12 @@ def call_together_api(model: str, messages: list[dict], temperature: float, max_
|
|
|
18
23
|
|
|
19
24
|
data = {"model": model, "messages": messages, "temperature": temperature, "max_tokens": max_tokens}
|
|
20
25
|
|
|
26
|
+
logger.debug(f"Calling Together AI API with model={model}")
|
|
27
|
+
|
|
21
28
|
try:
|
|
22
|
-
response = httpx.post(
|
|
29
|
+
response = httpx.post(
|
|
30
|
+
url, headers=headers, json=data, timeout=ProviderDefaults.HTTP_TIMEOUT, verify=get_ssl_verify()
|
|
31
|
+
)
|
|
23
32
|
response.raise_for_status()
|
|
24
33
|
response_data = response.json()
|
|
25
34
|
content = response_data["choices"][0]["message"]["content"]
|
|
@@ -27,6 +36,7 @@ def call_together_api(model: str, messages: list[dict], temperature: float, max_
|
|
|
27
36
|
raise AIError.model_error("Together AI API returned null content")
|
|
28
37
|
if content == "":
|
|
29
38
|
raise AIError.model_error("Together AI API returned empty content")
|
|
39
|
+
logger.debug("Together AI API response received successfully")
|
|
30
40
|
return content
|
|
31
41
|
except httpx.HTTPStatusError as e:
|
|
32
42
|
if e.response.status_code == 429:
|
gac/providers/zai.py
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"""Z.AI API provider for gac."""
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
6
7
|
|
|
8
|
+
from gac.constants import ProviderDefaults
|
|
7
9
|
from gac.errors import AIError
|
|
10
|
+
from gac.utils import get_ssl_verify
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
def _call_zai_api_impl(
|
|
@@ -18,8 +23,12 @@ def _call_zai_api_impl(
|
|
|
18
23
|
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
|
|
19
24
|
data = {"model": model, "messages": messages, "temperature": temperature, "max_tokens": max_tokens}
|
|
20
25
|
|
|
26
|
+
logger.debug(f"Calling {api_name} API with model={model}")
|
|
27
|
+
|
|
21
28
|
try:
|
|
22
|
-
response = httpx.post(
|
|
29
|
+
response = httpx.post(
|
|
30
|
+
url, headers=headers, json=data, timeout=ProviderDefaults.HTTP_TIMEOUT, verify=get_ssl_verify()
|
|
31
|
+
)
|
|
23
32
|
response.raise_for_status()
|
|
24
33
|
response_data = response.json()
|
|
25
34
|
|
|
@@ -32,6 +41,7 @@ def _call_zai_api_impl(
|
|
|
32
41
|
raise AIError.model_error(f"{api_name} API returned null content")
|
|
33
42
|
if content == "":
|
|
34
43
|
raise AIError.model_error(f"{api_name} API returned empty content")
|
|
44
|
+
logger.debug(f"{api_name} API response received successfully")
|
|
35
45
|
return content
|
|
36
46
|
else:
|
|
37
47
|
raise AIError.model_error(f"{api_name} API response missing content: {response_data}")
|
gac/utils.py
CHANGED
|
@@ -2,16 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
import locale
|
|
4
4
|
import logging
|
|
5
|
+
import os
|
|
5
6
|
import subprocess
|
|
6
7
|
import sys
|
|
8
|
+
from functools import lru_cache
|
|
7
9
|
|
|
8
10
|
from rich.console import Console
|
|
9
11
|
from rich.theme import Theme
|
|
10
12
|
|
|
11
|
-
from gac.constants import Logging
|
|
13
|
+
from gac.constants import EnvDefaults, Logging
|
|
12
14
|
from gac.errors import GacError
|
|
13
15
|
|
|
14
16
|
|
|
17
|
+
@lru_cache(maxsize=1)
|
|
18
|
+
def should_skip_ssl_verification() -> bool:
|
|
19
|
+
"""Return True when SSL certificate verification should be skipped.
|
|
20
|
+
|
|
21
|
+
This is useful for corporate environments with proxy servers that
|
|
22
|
+
intercept SSL traffic and cause certificate verification failures.
|
|
23
|
+
|
|
24
|
+
Can be enabled via:
|
|
25
|
+
- GAC_NO_VERIFY_SSL=true environment variable
|
|
26
|
+
- --no-verify-ssl CLI flag (which sets the env var)
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
True if SSL verification should be skipped, False otherwise.
|
|
30
|
+
"""
|
|
31
|
+
value = os.getenv("GAC_NO_VERIFY_SSL", str(EnvDefaults.NO_VERIFY_SSL))
|
|
32
|
+
return value.lower() in ("true", "1", "yes", "on")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_ssl_verify() -> bool:
|
|
36
|
+
"""Get the SSL verification setting for httpx requests.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
True to verify SSL certificates (default), False to skip verification.
|
|
40
|
+
"""
|
|
41
|
+
return not should_skip_ssl_verification()
|
|
42
|
+
|
|
43
|
+
|
|
15
44
|
def setup_logging(
|
|
16
45
|
log_level: int | str = Logging.DEFAULT_LEVEL,
|
|
17
46
|
quiet: bool = False,
|
gac/workflow_utils.py
CHANGED
|
@@ -3,6 +3,7 @@ import tempfile
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
import click
|
|
6
|
+
from prompt_toolkit import prompt
|
|
6
7
|
from rich.console import Console
|
|
7
8
|
from rich.panel import Panel
|
|
8
9
|
|
|
@@ -157,13 +158,7 @@ def collect_interactive_answers(questions: list[str]) -> dict[str, str] | None:
|
|
|
157
158
|
console.print(f"[bold blue]Question {i}:[/bold blue] {question}")
|
|
158
159
|
|
|
159
160
|
try:
|
|
160
|
-
answer =
|
|
161
|
-
"Your answer",
|
|
162
|
-
type=str,
|
|
163
|
-
default="", # Allow empty input to skip
|
|
164
|
-
show_default=False,
|
|
165
|
-
prompt_suffix=": ",
|
|
166
|
-
).strip()
|
|
161
|
+
answer = prompt("Your answer: ").strip()
|
|
167
162
|
|
|
168
163
|
# Handle special commands
|
|
169
164
|
answer_lower = answer.lower()
|
|
@@ -183,7 +178,7 @@ def collect_interactive_answers(questions: list[str]) -> dict[str, str] | None:
|
|
|
183
178
|
answers[question] = answer
|
|
184
179
|
console.print("[dim]↳ Got it![/dim]")
|
|
185
180
|
|
|
186
|
-
except
|
|
181
|
+
except KeyboardInterrupt:
|
|
187
182
|
# User pressed Ctrl+C
|
|
188
183
|
console.print("\n[yellow]⚠️ Interactive mode aborted by user[/yellow]")
|
|
189
184
|
return None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gac
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.8.1
|
|
4
4
|
Summary: LLM-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
|
|
@@ -47,7 +47,7 @@ Description-Content-Type: text/markdown
|
|
|
47
47
|
# 🚀 Git Auto Commit (gac)
|
|
48
48
|
|
|
49
49
|
[](https://pypi.org/project/gac/)
|
|
50
|
-
[](https://www.python.org/downloads/)
|
|
51
51
|
[](https://github.com/cellwebb/gac/actions)
|
|
52
52
|
[](https://app.codecov.io/gh/cellwebb/gac)
|
|
53
53
|
[](https://github.com/astral-sh/ruff)
|
|
@@ -109,8 +109,8 @@ uv tool upgrade gac
|
|
|
109
109
|
- **Anthropic** • **Azure OpenAI** • **Cerebras** • **Chutes.ai** • **Claude Code (OAuth)**
|
|
110
110
|
- **DeepSeek** • **Fireworks** • **Gemini** • **Groq** • **Kimi for Coding** • **LM Studio**
|
|
111
111
|
- **MiniMax.io** • **Mistral AI** • **Moonshot AI** • **Ollama** • **OpenAI** • **OpenRouter**
|
|
112
|
-
- **Replicate** • **Streamlake** • **Synthetic.new** • **Together AI**
|
|
113
|
-
- **Custom Endpoints (Anthropic/OpenAI)**
|
|
112
|
+
- **Qwen.ai (OAuth)** • **Replicate** • **Streamlake** • **Synthetic.new** • **Together AI**
|
|
113
|
+
- **Z.AI** • **Z.AI Coding** • **Custom Endpoints (Anthropic/OpenAI)**
|
|
114
114
|
|
|
115
115
|
### 🧠 **Smart LLM Analysis**
|
|
116
116
|
|
|
@@ -262,6 +262,8 @@ Track real-time installation metrics and package download statistics.
|
|
|
262
262
|
## Getting Help
|
|
263
263
|
|
|
264
264
|
- **Full documentation**: [docs/USAGE.md](docs/en/USAGE.md) - Complete CLI reference
|
|
265
|
+
- **Claude Code OAuth**: [docs/CLAUDE_CODE.md](docs/en/CLAUDE_CODE.md) - Claude Code setup and authentication
|
|
266
|
+
- **Qwen.ai OAuth**: [docs/QWEN.md](docs/en/QWEN.md) - Qwen.ai setup and authentication
|
|
265
267
|
- **Custom prompts**: [docs/CUSTOM_SYSTEM_PROMPTS.md](docs/en/CUSTOM_SYSTEM_PROMPTS.md) - Customize commit message style
|
|
266
268
|
- **Troubleshooting**: [docs/TROUBLESHOOTING.md](docs/en/TROUBLESHOOTING.md) - Common issues and solutions
|
|
267
269
|
- **Contributing**: [docs/CONTRIBUTING.md](docs/en/CONTRIBUTING.md) - Development setup and guidelines
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
gac/__init__.py,sha256=z9yGInqtycFIT3g1ca24r-A3699hKVaRqGUI79wsmMc,415
|
|
2
|
+
gac/__version__.py,sha256=KrwCaC6wbdQ2R2fD_kzJyUu5mtDSBRAe_FPDHQiGA4I,66
|
|
3
|
+
gac/ai.py,sha256=HnXmRFmUJin5k755iBqSLgKYssjShjKXz9SwICEpMag,3835
|
|
4
|
+
gac/ai_utils.py,sha256=FHN-cbU6_ofICqJOdw1TmN2z1lcW1KqVC8xXFF38HwA,11081
|
|
5
|
+
gac/auth_cli.py,sha256=D1UcpOdyLqnKNJQTBq2lHCHBaxFZsRbM4Krvg-1-NfA,6822
|
|
6
|
+
gac/cli.py,sha256=MgzcRwBrgq10uczRpWh3rIVTvBGCBdvldZloqEwWQRQ,7940
|
|
7
|
+
gac/config.py,sha256=dycwZfB7i0XyNA8qySyxH1UpV0Dkw_FsCluB9SqUcZQ,4667
|
|
8
|
+
gac/config_cli.py,sha256=o8UEEoWwZJ7xmDUbNPZEnbdANd1nLb4HMpmqMbcbbaY,2376
|
|
9
|
+
gac/constants.py,sha256=ckzm2yM2-DA_98TRpetX5mzQ28TqJPGtm0cEZnRj_A8,9958
|
|
10
|
+
gac/diff_cli.py,sha256=wnVQ9OFGnM0d2Pj9WVjWbo0jxqIuRHVAwmb8wU9Pa3E,5676
|
|
11
|
+
gac/errors.py,sha256=ysDIVRCd0YQVTOW3Q6YzdolxCdtkoQCAFf3_jrqbjUY,7916
|
|
12
|
+
gac/git.py,sha256=_NRkOyb6u8SiPrG-t-7GspjdSp7yptmNj1gT8VexmcY,12913
|
|
13
|
+
gac/init_cli.py,sha256=UbldjcEjypHHpAn49tMddzaFQtwwAjlf8ZBQVPoz9YQ,2299
|
|
14
|
+
gac/language_cli.py,sha256=NHg8Q2cAjt4-VOaIYdU5FL_ISvSyu5rbgs232CqfhzM,12929
|
|
15
|
+
gac/main.py,sha256=W9OafYQ5_QP87RWZTBEvdEu-aCf8MPRhF5XnnZ28lCo,44193
|
|
16
|
+
gac/model_cli.py,sha256=p5bkPxJrXd7vyN2vPP91I-TPyqRdvO3X1P-nw_95BAI,18342
|
|
17
|
+
gac/preprocess.py,sha256=hk2p2X4-xVDvuy-T1VMzMa9k5fTUbhlWDyw89DCf81Q,15379
|
|
18
|
+
gac/prompt.py,sha256=3pLc6Sfe6VVc3WBNg-Y7yaHcfhwn4aEi01Ro32CZqtQ,36262
|
|
19
|
+
gac/security.py,sha256=QT91mBEo2Y7la-aXvKuF2zhWuoOSXb6PWKLJ93kSy2k,9926
|
|
20
|
+
gac/utils.py,sha256=CiUSiGasX2myqjMaZPgrM_WZlCFhFogvdxhNTc3kn4w,12637
|
|
21
|
+
gac/workflow_utils.py,sha256=rGN7PqTqeUFLn260gm3hKyzF1PDVVuEsV1i2QHu2EO4,8118
|
|
22
|
+
gac/oauth/__init__.py,sha256=wwfeIMGgpIAb8-ptLcSDyK_sM72HI1bkULyJm7BwVs8,614
|
|
23
|
+
gac/oauth/claude_code.py,sha256=UqHrB2VbJsKeB2dq2T7qcScUPxCE1PaYCD5S3VwsLfU,14101
|
|
24
|
+
gac/oauth/qwen_oauth.py,sha256=Gs2L7VM8FopAE9-wzWyC64MNPmsBu8GrDI2vncqE0GI,10995
|
|
25
|
+
gac/oauth/token_store.py,sha256=d-MfgB3_hfqmn90hR73ajqNRgrPnoQLJN_Bra00Bfsw,2523
|
|
26
|
+
gac/providers/__init__.py,sha256=xUtR2-MZRrRVC0A51M6BsiN2cdth52BZVIEbDkH6Wdc,2969
|
|
27
|
+
gac/providers/anthropic.py,sha256=lqOmnHbHde6pifOogclPL9Wvb-4YPIB9wQDvI346dC0,2374
|
|
28
|
+
gac/providers/azure_openai.py,sha256=paH6LJL_mA-812QutfMbKmoPpenQMirolhQ7x70vtiE,4072
|
|
29
|
+
gac/providers/cerebras.py,sha256=WsqT5pTE-j7psOshddyIBAGdXD3Twxqtdym-gaM_-vQ,1984
|
|
30
|
+
gac/providers/chutes.py,sha256=xBoOcawwCKjqVk26W-yYfgewn-sCbBEet36U9PSYyNw,2955
|
|
31
|
+
gac/providers/claude_code.py,sha256=RwxOT7ARgRlUazPgU4mfzYpSW6P12NxttK-WfJJc6pw,4411
|
|
32
|
+
gac/providers/custom_anthropic.py,sha256=XdHv_OXeIi2SkIUCYeEV_q3InOvrYOHBZJ0P-rTJohM,5682
|
|
33
|
+
gac/providers/custom_openai.py,sha256=ImwWBcda5Gr51gPtBdUL2ApLHx3eEHV8e-9SfYxMaao,4095
|
|
34
|
+
gac/providers/deepseek.py,sha256=r3V5jPm0zPba8XIcZwswM1wXw8V6JWe5JVogmA6XsY8,1979
|
|
35
|
+
gac/providers/fireworks.py,sha256=v2qPfE3cSRQOIPrSiWRcD0aS-p-Cu82IdHXXOk9kIrQ,2032
|
|
36
|
+
gac/providers/gemini.py,sha256=GN6AsUbaidrM6blVD65TAE2hmACbOQBbIIW849jM0hI,3680
|
|
37
|
+
gac/providers/groq.py,sha256=r780wFe40niJ1ObxbYEU3SbR0Nsewrfxwmk51MFWTsk,2959
|
|
38
|
+
gac/providers/kimi_coding.py,sha256=PaCuqtBB3PWDYb36-tMfQUJpoLoqoMti5bMRhRYvVoU,2880
|
|
39
|
+
gac/providers/lmstudio.py,sha256=NTHig1naUm01R2GriGVAxozoPJulQZT2AK_kRlWEzSU,2561
|
|
40
|
+
gac/providers/minimax.py,sha256=-_mS5FajMLgXcz-K6-dhIo6Obk5ML4sMLduEQsvmGSs,1964
|
|
41
|
+
gac/providers/mistral.py,sha256=pUJ0mDbxK8WXH5AUJ8d2g5eoyI2FBkdnqbv4ijpP4Vw,1964
|
|
42
|
+
gac/providers/moonshot.py,sha256=UEEfgNhd2I3cDw2IwlC19u0ufLEM4AWgp0WW0PS2wmE,2004
|
|
43
|
+
gac/providers/ollama.py,sha256=OFKDnzFyzG7_OGPDgiK367-7FKuXmr84LFU9kL1iJjI,2427
|
|
44
|
+
gac/providers/openai.py,sha256=nsiOXljNfB_eeaRu09OIwHZpGuhF5WoXWCx99Hz7Kdo,1962
|
|
45
|
+
gac/providers/openrouter.py,sha256=tFmC9KfLcNAEFiiBxEuX5pzgVuXa6cdtUKmnKLtadpk,2544
|
|
46
|
+
gac/providers/qwen.py,sha256=xw0N2Tx0_FVFi_RPFxZgPcGlvexhpHSp7XVh7ej2Za4,2983
|
|
47
|
+
gac/providers/replicate.py,sha256=ScSz-Bzin77VG3XZowc-mIHA2Nj9B2NTeMPHmFZOFdY,4212
|
|
48
|
+
gac/providers/streamlake.py,sha256=_YAcEqmn6YFUzIN1NjKavGaqF5j1DyyrB5MlwB6omgY,2387
|
|
49
|
+
gac/providers/synthetic.py,sha256=U7XGtReX7extGOp_qvVrAcFcq4hdfcdAF2y7oURevBc,2201
|
|
50
|
+
gac/providers/together.py,sha256=Bg1cb4DCSjgdZoa2RDyt9hC9NYTcXZJ_b5MZ4vWlFp8,2009
|
|
51
|
+
gac/providers/zai.py,sha256=RC_wWOrs1OtPlkOVsBqQ0BqYF7DSymqHq6gZznhCEbk,3088
|
|
52
|
+
gac-3.8.1.dist-info/METADATA,sha256=A22DCTy3KBqB2BNifXjpFszAnov2TuRo0WgKF4uRpQg,11438
|
|
53
|
+
gac-3.8.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
54
|
+
gac-3.8.1.dist-info/entry_points.txt,sha256=tdjN-XMmcWfL92swuRAjT62bFLOAwk9bTMRLGP5Z4aI,36
|
|
55
|
+
gac-3.8.1.dist-info/licenses/LICENSE,sha256=vOab37NouL1PNs5BswnPayrMCqaN2sqLfMQfqPDrpZg,1103
|
|
56
|
+
gac-3.8.1.dist-info/RECORD,,
|
gac-3.6.0.dist-info/RECORD
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
gac/__init__.py,sha256=z9yGInqtycFIT3g1ca24r-A3699hKVaRqGUI79wsmMc,415
|
|
2
|
-
gac/__version__.py,sha256=QjkK28WCwoefBMwiKqFYy76cOVTGklvGTI3wsZ1eIDk,66
|
|
3
|
-
gac/ai.py,sha256=HnXmRFmUJin5k755iBqSLgKYssjShjKXz9SwICEpMag,3835
|
|
4
|
-
gac/ai_utils.py,sha256=YpMEXCXkY1KqLIoYOmMGwVzTxUq-jof_v8VYbsgFMl0,8940
|
|
5
|
-
gac/auth_cli.py,sha256=Bd2TSjoVruOwzcPjDvyjfuKtlBr_wEScf8AWsddKfU0,2224
|
|
6
|
-
gac/cli.py,sha256=ZbUGyKHuxfW1p6zaiTl8FU_tIYaxPN36tCxLYBinDFk,7450
|
|
7
|
-
gac/config.py,sha256=_EWAtHL9FMrvO4wD0ReZQEstKzhF1f2rbSm9dWCT350,2155
|
|
8
|
-
gac/config_cli.py,sha256=o8UEEoWwZJ7xmDUbNPZEnbdANd1nLb4HMpmqMbcbbaY,2376
|
|
9
|
-
gac/constants.py,sha256=nd8aiNCAsvP1OM4VWwXjonqA7RAtPwTheA__GrVuP5o,9700
|
|
10
|
-
gac/diff_cli.py,sha256=wnVQ9OFGnM0d2Pj9WVjWbo0jxqIuRHVAwmb8wU9Pa3E,5676
|
|
11
|
-
gac/errors.py,sha256=ysDIVRCd0YQVTOW3Q6YzdolxCdtkoQCAFf3_jrqbjUY,7916
|
|
12
|
-
gac/git.py,sha256=_NRkOyb6u8SiPrG-t-7GspjdSp7yptmNj1gT8VexmcY,12913
|
|
13
|
-
gac/init_cli.py,sha256=UbldjcEjypHHpAn49tMddzaFQtwwAjlf8ZBQVPoz9YQ,2299
|
|
14
|
-
gac/language_cli.py,sha256=NHg8Q2cAjt4-VOaIYdU5FL_ISvSyu5rbgs232CqfhzM,12929
|
|
15
|
-
gac/main.py,sha256=jL26ti3t3-3ykV20tJaOdNsDFPKJoqKZX1fg20uYLGM,41872
|
|
16
|
-
gac/model_cli.py,sha256=DGI8V6QWyI07KeVYJMzXTMxqQg4crhnSfuOUYiZYygE,16013
|
|
17
|
-
gac/preprocess.py,sha256=hk2p2X4-xVDvuy-T1VMzMa9k5fTUbhlWDyw89DCf81Q,15379
|
|
18
|
-
gac/prompt.py,sha256=MzW-OzixAOltVcIVaRp6_hm8HscxRcmxj9Jh94P6Rvo,35454
|
|
19
|
-
gac/security.py,sha256=QT91mBEo2Y7la-aXvKuF2zhWuoOSXb6PWKLJ93kSy2k,9926
|
|
20
|
-
gac/utils.py,sha256=gTpc9zLzy3-3L5k-V5uSeFI-NnSPabA1GGVwSgpeMSk,11709
|
|
21
|
-
gac/workflow_utils.py,sha256=-O4QRfY1bbv2lh1tpTaAEd_N0OE4eHV6E_vRvzBCFtk,8268
|
|
22
|
-
gac/oauth/__init__.py,sha256=hPSGHlt-BFZXSodg-n6S405-5YZComyV_iEtzkPumdQ,46
|
|
23
|
-
gac/oauth/claude_code.py,sha256=S4XsamRKOJoBwXo3GyhhcP5ypj3RE2akoBSo2yojtS8,12120
|
|
24
|
-
gac/providers/__init__.py,sha256=th44JWjSQl8YgbLUmbRHXZS8jDXDFuBLeKpXDhL979w,2889
|
|
25
|
-
gac/providers/anthropic.py,sha256=VK5d1s1PmBNDwh_x7illQ2CIZIHNIYU28btVfizwQPs,2036
|
|
26
|
-
gac/providers/azure_openai.py,sha256=X1T1jtJDQmTw2Qm_I2onzEUDpfRQ49mj1WDGBZ3pXlI,3919
|
|
27
|
-
gac/providers/cerebras.py,sha256=Ik8lhlsliGJVkgDgqlThfpra9tqbdYQZkaC4eNxRd9w,1648
|
|
28
|
-
gac/providers/chutes.py,sha256=cclJOLuGVIiiaF-9Bs1kH6SSOhEmduGB2zZ86KIaXKw,2617
|
|
29
|
-
gac/providers/claude_code.py,sha256=e_j0n0flN6m1UsY_v1lzwcy1miC9pynPY-1Fbq2akyw,4069
|
|
30
|
-
gac/providers/custom_anthropic.py,sha256=aqtMdLnbwFjXkQzo7-pKfhIHktFuePVsnfDJOFJvDeM,5529
|
|
31
|
-
gac/providers/custom_openai.py,sha256=kLRfClY6kdN8FGsFMYJVFCL82d34tnHZ9IPSZ2VPK2Q,3942
|
|
32
|
-
gac/providers/deepseek.py,sha256=leT2S4_CE6JzwF3skDd4umBsu2rkJOJ66AfOdSL5wGc,1643
|
|
33
|
-
gac/providers/fireworks.py,sha256=zsWhf6LMVdtsD9keXRFwgn9lCQigz6VmrDl6vqIVkdI,1688
|
|
34
|
-
gac/providers/gemini.py,sha256=kl9WKdPm_ANYk0hsrUyMdACzR0cm8Eui9M1IwObYW-4,3348
|
|
35
|
-
gac/providers/groq.py,sha256=9v2fAjDa_iRNHFptiUBN8Vt7ZDKkW_JOmIBeYvycD1M,2806
|
|
36
|
-
gac/providers/kimi_coding.py,sha256=Nj8iojesCvCbwEEH3F8xNchIE_fmA1S2SMjGhD9arek,2727
|
|
37
|
-
gac/providers/lmstudio.py,sha256=R82-f0tWdFfGQxLT6o3Q2tfvYguF7ESUg9DEUHNyrDk,2146
|
|
38
|
-
gac/providers/minimax.py,sha256=oI5rEVlkcYenNUNH53zS00X8NqpcZ1gMsTGzQCsmes4,1630
|
|
39
|
-
gac/providers/mistral.py,sha256=b2Du1nJutKjmJXmsXz4Ne43Yn52OSS0q6BKGoZnfH8Q,1630
|
|
40
|
-
gac/providers/moonshot.py,sha256=Wy0RdYlKCkeRBv40jAJkybjXh420eb2btrTPTLioTbQ,1662
|
|
41
|
-
gac/providers/ollama.py,sha256=hPkagbhEiAoH9RTET4EQe9-lTL0YmMRCbQ5dVbRQw6Q,2095
|
|
42
|
-
gac/providers/openai.py,sha256=iHVD6bHf57W-QmW7u1Ee5vOpev7XZ-K75NcolLfebOk,1630
|
|
43
|
-
gac/providers/openrouter.py,sha256=H3ce8JcRUYq1I30lOjGESdX7jfoPkW3mKAYnc2aYfBw,2204
|
|
44
|
-
gac/providers/replicate.py,sha256=TjWZOIZBCq226zr_w0j0YpBxgtp0VY33yryd8q9akuo,3785
|
|
45
|
-
gac/providers/streamlake.py,sha256=KAA2ZnpuEI5imzvdWVWUhEBHSP0BMnprKXte6CbwBWY,2047
|
|
46
|
-
gac/providers/synthetic.py,sha256=sRMIJTS9LpcXd9A7qp_ZjZxdqtTKRn9fl1W4YwJZP4c,1855
|
|
47
|
-
gac/providers/together.py,sha256=1bUIVHfYzcEDw4hQPE8qV6hjc2JNHPv_khVgpk2IJxI,1667
|
|
48
|
-
gac/providers/zai.py,sha256=kywhhrCfPBu0rElZyb-iENxQxxpVGykvePuL4xrXlaU,2739
|
|
49
|
-
gac-3.6.0.dist-info/METADATA,sha256=aPkvY8fwgU4gtKZojVzp3nbsfCpeWVLNWwM4lAbeQ7g,11254
|
|
50
|
-
gac-3.6.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
51
|
-
gac-3.6.0.dist-info/entry_points.txt,sha256=tdjN-XMmcWfL92swuRAjT62bFLOAwk9bTMRLGP5Z4aI,36
|
|
52
|
-
gac-3.6.0.dist-info/licenses/LICENSE,sha256=vOab37NouL1PNs5BswnPayrMCqaN2sqLfMQfqPDrpZg,1103
|
|
53
|
-
gac-3.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|