gac 3.6.0__py3-none-any.whl → 3.10.10__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/__init__.py +4 -6
- gac/__version__.py +1 -1
- gac/ai_utils.py +59 -43
- gac/auth_cli.py +181 -36
- gac/cli.py +26 -9
- gac/commit_executor.py +59 -0
- gac/config.py +81 -2
- gac/config_cli.py +19 -7
- gac/constants/__init__.py +34 -0
- gac/constants/commit.py +63 -0
- gac/constants/defaults.py +40 -0
- gac/constants/file_patterns.py +110 -0
- gac/constants/languages.py +119 -0
- gac/diff_cli.py +0 -22
- gac/errors.py +8 -2
- gac/git.py +6 -6
- gac/git_state_validator.py +193 -0
- gac/grouped_commit_workflow.py +458 -0
- gac/init_cli.py +2 -1
- gac/interactive_mode.py +179 -0
- gac/language_cli.py +0 -1
- gac/main.py +231 -926
- gac/model_cli.py +67 -11
- gac/model_identifier.py +70 -0
- gac/oauth/__init__.py +26 -0
- gac/oauth/claude_code.py +89 -22
- gac/oauth/qwen_oauth.py +327 -0
- gac/oauth/token_store.py +81 -0
- gac/oauth_retry.py +161 -0
- gac/postprocess.py +155 -0
- gac/prompt.py +21 -479
- gac/prompt_builder.py +88 -0
- gac/providers/README.md +437 -0
- gac/providers/__init__.py +70 -78
- gac/providers/anthropic.py +12 -46
- gac/providers/azure_openai.py +48 -88
- gac/providers/base.py +329 -0
- gac/providers/cerebras.py +10 -33
- gac/providers/chutes.py +16 -62
- gac/providers/claude_code.py +64 -87
- gac/providers/custom_anthropic.py +51 -81
- gac/providers/custom_openai.py +29 -83
- gac/providers/deepseek.py +10 -33
- gac/providers/error_handler.py +139 -0
- gac/providers/fireworks.py +10 -33
- gac/providers/gemini.py +66 -63
- gac/providers/groq.py +10 -58
- gac/providers/kimi_coding.py +19 -55
- gac/providers/lmstudio.py +64 -43
- gac/providers/minimax.py +10 -33
- gac/providers/mistral.py +10 -33
- gac/providers/moonshot.py +10 -33
- gac/providers/ollama.py +56 -33
- gac/providers/openai.py +30 -36
- gac/providers/openrouter.py +15 -52
- gac/providers/protocol.py +71 -0
- gac/providers/qwen.py +64 -0
- gac/providers/registry.py +58 -0
- gac/providers/replicate.py +140 -82
- gac/providers/streamlake.py +26 -46
- gac/providers/synthetic.py +35 -37
- gac/providers/together.py +10 -33
- gac/providers/zai.py +29 -57
- gac/py.typed +0 -0
- gac/security.py +1 -1
- gac/templates/__init__.py +1 -0
- gac/templates/question_generation.txt +60 -0
- gac/templates/system_prompt.txt +224 -0
- gac/templates/user_prompt.txt +28 -0
- gac/utils.py +36 -6
- gac/workflow_context.py +162 -0
- gac/workflow_utils.py +3 -8
- {gac-3.6.0.dist-info → gac-3.10.10.dist-info}/METADATA +6 -4
- gac-3.10.10.dist-info/RECORD +79 -0
- gac/constants.py +0 -321
- gac-3.6.0.dist-info/RECORD +0 -53
- {gac-3.6.0.dist-info → gac-3.10.10.dist-info}/WHEEL +0 -0
- {gac-3.6.0.dist-info → gac-3.10.10.dist-info}/entry_points.txt +0 -0
- {gac-3.6.0.dist-info → gac-3.10.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
<role>
|
|
2
|
+
You are an expert git commit message generator. Your task is to analyze code changes and create a concise, meaningful git commit message. You will receive git status and diff information. Your entire response will be used directly as a git commit message.
|
|
3
|
+
</role>
|
|
4
|
+
|
|
5
|
+
<focus>
|
|
6
|
+
Your commit message must reflect the core purpose and impact of these changes.
|
|
7
|
+
Prioritize the primary intent over implementation details.
|
|
8
|
+
Consider what future developers need to understand about this change.
|
|
9
|
+
Identify if this introduces new capabilities, fixes problems, or improves existing code.
|
|
10
|
+
</focus>
|
|
11
|
+
|
|
12
|
+
<mixed_changes>
|
|
13
|
+
When changes span multiple areas:
|
|
14
|
+
- Choose the commit type based on the PRIMARY purpose, not the largest file count
|
|
15
|
+
- Feature additions with supporting tests/docs should use 'feat'
|
|
16
|
+
- Bug fixes with added tests should use 'fix'
|
|
17
|
+
- Refactoring that improves multiple components should use 'refactor'
|
|
18
|
+
- Documentation updates are 'docs' only when that's the sole purpose
|
|
19
|
+
</mixed_changes>
|
|
20
|
+
|
|
21
|
+
<format>
|
|
22
|
+
<one_liner>
|
|
23
|
+
Create a single-line commit message.
|
|
24
|
+
Your message should be clear, concise, and descriptive of the core change.
|
|
25
|
+
Use present tense ("Add feature" not "Added feature").
|
|
26
|
+
</one_liner><multi_line>
|
|
27
|
+
Create a commit message with:
|
|
28
|
+
- First line: A concise summary that could stand alone
|
|
29
|
+
- Blank line after the summary
|
|
30
|
+
- Detailed body with multiple bullet points explaining the key changes
|
|
31
|
+
- Focus on WHY changes were made, not just WHAT was changed
|
|
32
|
+
- Order points from most important to least important
|
|
33
|
+
</multi_line><verbose>
|
|
34
|
+
IMPORTANT: You MUST create a MULTI-PARAGRAPH commit message with detailed sections.
|
|
35
|
+
DO NOT create a single-line commit message.
|
|
36
|
+
|
|
37
|
+
Your commit message MUST follow this structure:
|
|
38
|
+
|
|
39
|
+
Line 1: A concise summary (that could stand alone) with conventional commit prefix
|
|
40
|
+
Line 2: BLANK LINE (required)
|
|
41
|
+
Lines 3+: Detailed multi-paragraph body with the following sections:
|
|
42
|
+
|
|
43
|
+
## Motivation
|
|
44
|
+
Explain why this commit exists in 2-3 sentences. What problem does it solve? What need does it address?
|
|
45
|
+
|
|
46
|
+
## Architecture / Approach
|
|
47
|
+
Describe how it was implemented in 2-4 sentences. Include key design decisions and any rejected alternatives.
|
|
48
|
+
Reference specific modules, functions, or classes when relevant.
|
|
49
|
+
|
|
50
|
+
## Affected Components
|
|
51
|
+
List the main modules, subsystems, or directories impacted by this change.
|
|
52
|
+
|
|
53
|
+
OPTIONAL sections (include only if relevant):
|
|
54
|
+
|
|
55
|
+
## Performance / Security Impact
|
|
56
|
+
Describe any performance improvements, trade-offs, or security considerations.
|
|
57
|
+
Include concrete data such as benchmark results if available.
|
|
58
|
+
|
|
59
|
+
## Compatibility / Testing
|
|
60
|
+
Mention any compatibility considerations, known limitations, testing performed, or next steps for validation.
|
|
61
|
+
|
|
62
|
+
REQUIREMENTS:
|
|
63
|
+
- Your response MUST be at least 10 lines long with multiple paragraphs
|
|
64
|
+
- Use active voice and present tense ("Implements", "Adds", "Refactors")
|
|
65
|
+
- Provide concrete, specific information rather than vague descriptions
|
|
66
|
+
- Keep the tone professional and technical
|
|
67
|
+
- Focus on intent and reasoning, not just code changes
|
|
68
|
+
- Use markdown headers (##) for section organization
|
|
69
|
+
</verbose>
|
|
70
|
+
</format>
|
|
71
|
+
|
|
72
|
+
<conventions_no_scope>
|
|
73
|
+
You MUST start your commit message with the most appropriate conventional commit prefix.
|
|
74
|
+
|
|
75
|
+
IMPORTANT: Check file types FIRST when determining the commit type:
|
|
76
|
+
- If changes are ONLY to documentation files (*.md, *.rst, *.txt in docs/, README*, CHANGELOG*, etc.), ALWAYS use 'docs:'
|
|
77
|
+
- Use 'docs:' ONLY when ALL changes are documentation files - INCLUDING README updates, regardless of how significant the changes are
|
|
78
|
+
- If changes include both documentation and code, use the prefix for the code changes, unless it is a documentation-only change
|
|
79
|
+
|
|
80
|
+
Commit type prefixes:
|
|
81
|
+
- feat: A new feature or functionality addition
|
|
82
|
+
- fix: A bug fix or error correction
|
|
83
|
+
- docs: Documentation changes only (INCLUDING README updates, regardless of how significant)
|
|
84
|
+
- style: Changes to code style/formatting without logic changes
|
|
85
|
+
- refactor: Code restructuring without behavior changes
|
|
86
|
+
- perf: Performance improvements
|
|
87
|
+
- test: Adding/modifying tests
|
|
88
|
+
- build: Changes to build system/dependencies
|
|
89
|
+
- ci: Changes to CI configuration
|
|
90
|
+
- chore: Miscellaneous changes not affecting src/test files
|
|
91
|
+
|
|
92
|
+
Select ONE prefix that best matches the primary purpose of the changes.
|
|
93
|
+
If multiple prefixes apply, choose the one that represents the most significant change.
|
|
94
|
+
If you cannot confidently determine a type, use 'chore'.
|
|
95
|
+
|
|
96
|
+
Do NOT include a scope in your commit prefix.
|
|
97
|
+
</conventions_no_scope>
|
|
98
|
+
|
|
99
|
+
<conventions_with_scope>
|
|
100
|
+
You MUST write a conventional commit message with EXACTLY ONE type and an inferred scope.
|
|
101
|
+
|
|
102
|
+
FORMAT: type(scope): description
|
|
103
|
+
|
|
104
|
+
IMPORTANT: Check file types FIRST when determining the commit type:
|
|
105
|
+
- If changes are ONLY to documentation files (*.md, *.rst, *.txt in docs/, README*, CHANGELOG*, etc.), ALWAYS use 'docs'
|
|
106
|
+
- If changes include both documentation and code, use the prefix for the code changes, unless it is a documentation-only change
|
|
107
|
+
|
|
108
|
+
Select ONE type from this list that best matches the primary purpose of the changes:
|
|
109
|
+
- feat: A new feature or functionality addition
|
|
110
|
+
- fix: A bug fix or error correction
|
|
111
|
+
- docs: Documentation changes only (INCLUDING README and CHANGELOG updates, regardless of how significant)
|
|
112
|
+
- style: Changes to code style/formatting without logic changes
|
|
113
|
+
- refactor: Code restructuring without behavior changes
|
|
114
|
+
- perf: Performance improvements
|
|
115
|
+
- test: Adding/modifying tests
|
|
116
|
+
- build: Changes to build system/dependencies
|
|
117
|
+
- ci: Changes to CI configuration
|
|
118
|
+
- chore: Miscellaneous changes not affecting src/test files
|
|
119
|
+
|
|
120
|
+
You MUST infer an appropriate scope from the changes. A good scope is concise (usually one word) and indicates the component or area that was changed.
|
|
121
|
+
|
|
122
|
+
<scope_rules>
|
|
123
|
+
For scope inference, select the most specific component affected:
|
|
124
|
+
- Use module/component names from the codebase (auth, api, cli, core)
|
|
125
|
+
- Use functional areas for cross-cutting changes (config, build, test)
|
|
126
|
+
- Keep scopes consistent with existing commit history when possible
|
|
127
|
+
- Prefer established patterns over creating new scope names
|
|
128
|
+
- Use singular form (auth, not auths; test, not tests)
|
|
129
|
+
</scope_rules>
|
|
130
|
+
|
|
131
|
+
Examples of good scopes: api, auth, ui, core, docs, build, prompt, config
|
|
132
|
+
|
|
133
|
+
CORRECT EXAMPLES (these formats are correct):
|
|
134
|
+
feat(auth): add login functionality
|
|
135
|
+
fix(api): resolve null response issue
|
|
136
|
+
refactor(core): improve data processing
|
|
137
|
+
docs(readme): update installation instructions
|
|
138
|
+
|
|
139
|
+
INCORRECT EXAMPLES (these formats are wrong and must NOT be used):
|
|
140
|
+
chore: feat(component): description
|
|
141
|
+
fix: refactor(component): description
|
|
142
|
+
feat: feat(component): description
|
|
143
|
+
chore: chore(component): description
|
|
144
|
+
|
|
145
|
+
You MUST NOT prefix the type(scope) with another type. Use EXACTLY ONE type, which MUST include the scope in parentheses.
|
|
146
|
+
</conventions_with_scope>
|
|
147
|
+
|
|
148
|
+
<examples_no_scope>
|
|
149
|
+
Good commit messages (no scope):
|
|
150
|
+
[OK] feat: add OAuth2 integration with Google and GitHub
|
|
151
|
+
[OK] fix: resolve race condition in user session management
|
|
152
|
+
[OK] docs: add troubleshooting section for common installation issues
|
|
153
|
+
[OK] refactor: extract validation logic into reusable utilities
|
|
154
|
+
[OK] test: add comprehensive unit tests for token validation
|
|
155
|
+
[OK] build: upgrade to latest security patches
|
|
156
|
+
|
|
157
|
+
Bad commit messages:
|
|
158
|
+
[ERROR] fix stuff
|
|
159
|
+
[ERROR] update code
|
|
160
|
+
[ERROR] feat(auth): add login (scope included when not requested)
|
|
161
|
+
[ERROR] WIP: still working on this
|
|
162
|
+
[ERROR] Fixed bug
|
|
163
|
+
[ERROR] Changes
|
|
164
|
+
</examples_no_scope>
|
|
165
|
+
|
|
166
|
+
<examples_verbose_no_scope>
|
|
167
|
+
Example of a good VERBOSE commit message (without scope):
|
|
168
|
+
|
|
169
|
+
feat: add verbose mode for detailed commit message generation
|
|
170
|
+
|
|
171
|
+
## Motivation
|
|
172
|
+
Users need the ability to generate comprehensive commit messages that follow best practices for code review and documentation. The existing one-liner and multi-line modes don't provide sufficient structure for complex changes that require detailed explanations of motivation, architecture decisions, and impact.
|
|
173
|
+
|
|
174
|
+
## Architecture / Approach
|
|
175
|
+
Adds a new --verbose/-v flag to the CLI that modifies the prompt generation in build_prompt(). When enabled, the prompt instructs the AI to generate commit messages with structured sections including Motivation, Architecture/Approach, Affected Components, and optional Performance/Testing sections. The implementation uses the existing format selection logic with verbose taking priority over one_liner and multi_line modes.
|
|
176
|
+
|
|
177
|
+
## Affected Components
|
|
178
|
+
- src/gac/cli.py: Added --verbose flag and parameter passing
|
|
179
|
+
- src/gac/main.py: Extended main() to accept and pass verbose parameter
|
|
180
|
+
- src/gac/prompt.py: Added <verbose> template section with detailed instructions
|
|
181
|
+
- tests/test_prompt.py: Added test coverage for verbose mode
|
|
182
|
+
|
|
183
|
+
## Compatibility / Testing
|
|
184
|
+
Added new test test_build_prompt_verbose_mode to verify the verbose template generation. All existing tests pass. The verbose mode is opt-in via the -v flag, maintaining backward compatibility.
|
|
185
|
+
</examples_verbose_no_scope>
|
|
186
|
+
|
|
187
|
+
<examples_verbose_with_scope>
|
|
188
|
+
Example of a good VERBOSE commit message (with scope):
|
|
189
|
+
|
|
190
|
+
feat(cli): add verbose mode for detailed commit message generation
|
|
191
|
+
|
|
192
|
+
## Motivation
|
|
193
|
+
Users need the ability to generate comprehensive commit messages that follow best practices for code review and documentation. The existing one-liner and multi-line modes don't provide sufficient structure for complex changes that require detailed explanations of motivation, architecture decisions, and impact.
|
|
194
|
+
|
|
195
|
+
## Architecture / Approach
|
|
196
|
+
Adds a new --verbose/-v flag to the CLI that modifies the prompt generation in build_prompt(). When enabled, the prompt instructs the AI to generate commit messages with structured sections including Motivation, Architecture/Approach, Affected Components, and optional Performance/Testing sections. The implementation uses the existing format selection logic with verbose taking priority over one_liner and multi_line modes.
|
|
197
|
+
|
|
198
|
+
## Affected Components
|
|
199
|
+
- src/gac/cli.py: Added --verbose flag and parameter passing
|
|
200
|
+
- src/gac/main.py: Extended main() to accept and pass verbose parameter
|
|
201
|
+
- src/gac/prompt.py: Added <verbose> template section with detailed instructions
|
|
202
|
+
- tests/test_prompt.py: Added test coverage for verbose mode
|
|
203
|
+
|
|
204
|
+
## Compatibility / Testing
|
|
205
|
+
Added new test test_build_prompt_verbose_mode to verify the verbose template generation. All existing tests pass. The verbose mode is opt-in via the -v flag, maintaining backward compatibility.
|
|
206
|
+
</examples_verbose_with_scope>
|
|
207
|
+
|
|
208
|
+
<examples_with_scope>
|
|
209
|
+
Good commit message top lines (with scope):
|
|
210
|
+
[OK] feat(auth): add OAuth2 integration with Google and GitHub
|
|
211
|
+
[OK] fix(api): resolve race condition in user session management
|
|
212
|
+
[OK] docs(readme): add troubleshooting section for common installation issues
|
|
213
|
+
[OK] refactor(core): extract validation logic into reusable utilities
|
|
214
|
+
[OK] test(auth): add comprehensive unit tests for token validation
|
|
215
|
+
[OK] build(deps): upgrade to latest security patches
|
|
216
|
+
|
|
217
|
+
Bad commit messages:
|
|
218
|
+
[ERROR] fix stuff
|
|
219
|
+
[ERROR] update code
|
|
220
|
+
[ERROR] feat: fix(auth): add login (double prefix)
|
|
221
|
+
[ERROR] WIP: still working on this
|
|
222
|
+
[ERROR] Fixed bug
|
|
223
|
+
[ERROR] Changes
|
|
224
|
+
</examples_with_scope>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<hint>
|
|
2
|
+
Additional context provided by the user: <hint_text></hint_text>
|
|
3
|
+
</hint>
|
|
4
|
+
|
|
5
|
+
<git_diff>
|
|
6
|
+
<diff></diff>
|
|
7
|
+
</git_diff>
|
|
8
|
+
|
|
9
|
+
<git_diff_stat>
|
|
10
|
+
<diff_stat></diff_stat>
|
|
11
|
+
</git_diff_stat>
|
|
12
|
+
|
|
13
|
+
<git_status>
|
|
14
|
+
<status></status>
|
|
15
|
+
</git_status>
|
|
16
|
+
|
|
17
|
+
<language_instructions>
|
|
18
|
+
IMPORTANT: You MUST write the entire commit message in <language_name></language_name>.
|
|
19
|
+
All text in the commit message, including the summary line and body, must be in <language_name></language_name>.
|
|
20
|
+
<prefix_instruction></prefix_instruction>
|
|
21
|
+
</language_instructions>
|
|
22
|
+
|
|
23
|
+
<format_instructions>
|
|
24
|
+
IMMEDIATELY AFTER ANALYZING THE CHANGES, RESPOND WITH ONLY THE COMMIT MESSAGE.
|
|
25
|
+
DO NOT include any preamble, reasoning, explanations or anything other than the commit message itself.
|
|
26
|
+
DO NOT use markdown formatting, headers, or code blocks.
|
|
27
|
+
The entire response will be passed directly to 'git commit -m'.
|
|
28
|
+
</format_instructions>
|
gac/utils.py
CHANGED
|
@@ -2,16 +2,46 @@
|
|
|
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
|
|
9
|
+
from typing import Any
|
|
7
10
|
|
|
8
11
|
from rich.console import Console
|
|
9
12
|
from rich.theme import Theme
|
|
10
13
|
|
|
11
|
-
from gac.constants import Logging
|
|
14
|
+
from gac.constants import EnvDefaults, Logging
|
|
12
15
|
from gac.errors import GacError
|
|
13
16
|
|
|
14
17
|
|
|
18
|
+
@lru_cache(maxsize=1)
|
|
19
|
+
def should_skip_ssl_verification() -> bool:
|
|
20
|
+
"""Return True when SSL certificate verification should be skipped.
|
|
21
|
+
|
|
22
|
+
This is useful for corporate environments with proxy servers that
|
|
23
|
+
intercept SSL traffic and cause certificate verification failures.
|
|
24
|
+
|
|
25
|
+
Can be enabled via:
|
|
26
|
+
- GAC_NO_VERIFY_SSL=true environment variable
|
|
27
|
+
- --no-verify-ssl CLI flag (which sets the env var)
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
True if SSL verification should be skipped, False otherwise.
|
|
31
|
+
"""
|
|
32
|
+
value = os.getenv("GAC_NO_VERIFY_SSL", str(EnvDefaults.NO_VERIFY_SSL))
|
|
33
|
+
return value.lower() in ("true", "1", "yes", "on")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_ssl_verify() -> bool:
|
|
37
|
+
"""Get the SSL verification setting for httpx requests.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
True to verify SSL certificates (default), False to skip verification.
|
|
41
|
+
"""
|
|
42
|
+
return not should_skip_ssl_verification()
|
|
43
|
+
|
|
44
|
+
|
|
15
45
|
def setup_logging(
|
|
16
46
|
log_level: int | str = Logging.DEFAULT_LEVEL,
|
|
17
47
|
quiet: bool = False,
|
|
@@ -32,13 +62,13 @@ def setup_logging(
|
|
|
32
62
|
if quiet:
|
|
33
63
|
log_level = logging.ERROR
|
|
34
64
|
|
|
35
|
-
kwargs = {"force": force} if force else {}
|
|
65
|
+
kwargs: dict[str, Any] = {"force": force} if force else {}
|
|
36
66
|
|
|
37
67
|
logging.basicConfig(
|
|
38
68
|
level=log_level,
|
|
39
69
|
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
40
70
|
datefmt="%Y-%m-%d %H:%M:%S",
|
|
41
|
-
**kwargs,
|
|
71
|
+
**kwargs,
|
|
42
72
|
)
|
|
43
73
|
|
|
44
74
|
if suppress_noisy:
|
|
@@ -313,19 +343,19 @@ def edit_commit_message_inplace(message: str) -> str | None:
|
|
|
313
343
|
kb = KeyBindings()
|
|
314
344
|
|
|
315
345
|
@kb.add("c-s")
|
|
316
|
-
def _(event):
|
|
346
|
+
def _(event: Any) -> None:
|
|
317
347
|
"""Submit with Ctrl+S."""
|
|
318
348
|
submitted["value"] = True
|
|
319
349
|
event.app.exit()
|
|
320
350
|
|
|
321
351
|
@kb.add("c-c")
|
|
322
|
-
def _(event):
|
|
352
|
+
def _(event: Any) -> None:
|
|
323
353
|
"""Cancel editing."""
|
|
324
354
|
cancelled["value"] = True
|
|
325
355
|
event.app.exit()
|
|
326
356
|
|
|
327
357
|
@kb.add("escape", "enter")
|
|
328
|
-
def _(event):
|
|
358
|
+
def _(event: Any) -> None:
|
|
329
359
|
"""Submit with Esc+Enter."""
|
|
330
360
|
submitted["value"] = True
|
|
331
361
|
event.app.exit()
|
gac/workflow_context.py
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""Workflow context objects to reduce parameter explosion.
|
|
2
|
+
|
|
3
|
+
These dataclasses bundle related parameters that are passed through
|
|
4
|
+
the commit workflow, making function signatures cleaner and more maintainable.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from gac.commit_executor import CommitExecutor
|
|
14
|
+
from gac.git_state_validator import GitState
|
|
15
|
+
from gac.interactive_mode import InteractiveMode
|
|
16
|
+
from gac.prompt_builder import PromptBundle
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True)
|
|
20
|
+
class CLIOptions:
|
|
21
|
+
"""Options passed from CLI to main workflow.
|
|
22
|
+
|
|
23
|
+
Bundles all command-line arguments to reduce parameter explosion in main().
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
# Git workflow options
|
|
27
|
+
stage_all: bool = False
|
|
28
|
+
push: bool = False
|
|
29
|
+
no_verify: bool = False
|
|
30
|
+
hook_timeout: int = 120
|
|
31
|
+
|
|
32
|
+
# Workflow mode
|
|
33
|
+
group: bool = False
|
|
34
|
+
interactive: bool = False
|
|
35
|
+
require_confirmation: bool = True
|
|
36
|
+
dry_run: bool = False
|
|
37
|
+
|
|
38
|
+
# AI/Model config
|
|
39
|
+
model: str | None = None
|
|
40
|
+
|
|
41
|
+
# Prompt/output format config
|
|
42
|
+
hint: str = ""
|
|
43
|
+
one_liner: bool = False
|
|
44
|
+
infer_scope: bool = False
|
|
45
|
+
verbose: bool = False
|
|
46
|
+
language: str | None = None
|
|
47
|
+
|
|
48
|
+
# Output config
|
|
49
|
+
quiet: bool = False
|
|
50
|
+
message_only: bool = False
|
|
51
|
+
show_prompt: bool = False
|
|
52
|
+
|
|
53
|
+
# Security
|
|
54
|
+
skip_secret_scan: bool = False
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass(frozen=True)
|
|
58
|
+
class GenerationConfig:
|
|
59
|
+
"""Configuration for AI message generation.
|
|
60
|
+
|
|
61
|
+
These settings control how the AI model generates commit messages.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
model: str
|
|
65
|
+
temperature: float
|
|
66
|
+
max_output_tokens: int
|
|
67
|
+
max_retries: int
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass(frozen=True)
|
|
71
|
+
class WorkflowFlags:
|
|
72
|
+
"""Boolean flags controlling workflow behavior.
|
|
73
|
+
|
|
74
|
+
These flags determine how the commit workflow executes.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
require_confirmation: bool
|
|
78
|
+
quiet: bool
|
|
79
|
+
no_verify: bool
|
|
80
|
+
dry_run: bool
|
|
81
|
+
message_only: bool
|
|
82
|
+
push: bool
|
|
83
|
+
show_prompt: bool
|
|
84
|
+
interactive: bool
|
|
85
|
+
hook_timeout: int = 120
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass
|
|
89
|
+
class WorkflowState:
|
|
90
|
+
"""Runtime state for a commit workflow.
|
|
91
|
+
|
|
92
|
+
Contains the prompts, git state, and executor instances needed
|
|
93
|
+
to execute the workflow. This is mutable as conversation messages
|
|
94
|
+
may be updated during interactive flows.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
prompts: PromptBundle
|
|
98
|
+
git_state: GitState
|
|
99
|
+
hint: str
|
|
100
|
+
commit_executor: CommitExecutor
|
|
101
|
+
interactive_mode: InteractiveMode
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@dataclass(frozen=True)
|
|
105
|
+
class WorkflowContext:
|
|
106
|
+
"""Complete context for executing a commit workflow.
|
|
107
|
+
|
|
108
|
+
Bundles all configuration, flags, and state needed to execute
|
|
109
|
+
a single or grouped commit workflow.
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
config: GenerationConfig
|
|
113
|
+
flags: WorkflowFlags
|
|
114
|
+
state: WorkflowState
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def model(self) -> str:
|
|
118
|
+
return self.config.model
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def temperature(self) -> float:
|
|
122
|
+
return self.config.temperature
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def max_output_tokens(self) -> int:
|
|
126
|
+
return self.config.max_output_tokens
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def max_retries(self) -> int:
|
|
130
|
+
return self.config.max_retries
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def quiet(self) -> bool:
|
|
134
|
+
return self.flags.quiet
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def dry_run(self) -> bool:
|
|
138
|
+
return self.flags.dry_run
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def message_only(self) -> bool:
|
|
142
|
+
return self.flags.message_only
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def interactive(self) -> bool:
|
|
146
|
+
return self.flags.interactive
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def system_prompt(self) -> str:
|
|
150
|
+
return self.state.prompts.system_prompt
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def user_prompt(self) -> str:
|
|
154
|
+
return self.state.prompts.user_prompt
|
|
155
|
+
|
|
156
|
+
@property
|
|
157
|
+
def hint(self) -> str:
|
|
158
|
+
return self.state.hint
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def git_state(self) -> GitState:
|
|
162
|
+
return self.state.git_state
|
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.10.10
|
|
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,79 @@
|
|
|
1
|
+
gac/__init__.py,sha256=8MQ-da47gfj3k-K3zC8dVdW-F9R7DzxADILJyPPsvbo,311
|
|
2
|
+
gac/__version__.py,sha256=5bYvim4LGM_rUaBfwXdOz2SItoM3knux0OvqtnhBQdo,68
|
|
3
|
+
gac/ai.py,sha256=HnXmRFmUJin5k755iBqSLgKYssjShjKXz9SwICEpMag,3835
|
|
4
|
+
gac/ai_utils.py,sha256=jrfY_whmRdpUEyTSr_uxUuCfy_wpA4EIKhHE8jZ73sY,9872
|
|
5
|
+
gac/auth_cli.py,sha256=D1UcpOdyLqnKNJQTBq2lHCHBaxFZsRbM4Krvg-1-NfA,6822
|
|
6
|
+
gac/cli.py,sha256=aW7-EC3PhngvR11fVasPgu66aGgom16xc9PoRwG8fo4,8040
|
|
7
|
+
gac/commit_executor.py,sha256=0hhRQFuCpgsCRnP9AGq1V1JIVOAhZrqqRiSDZmoHkCk,2286
|
|
8
|
+
gac/config.py,sha256=qaQ7-udCA0Gb-S8aKEGM40ywVWQyMPtTpnBPq3BTkhg,5208
|
|
9
|
+
gac/config_cli.py,sha256=6tUoi-Xcexv5i2Y6p-wobrYlzeH2DNxlHMkyhFnFBYk,2994
|
|
10
|
+
gac/diff_cli.py,sha256=roBnoPcMn58rMGA475lqXlC2iYERC-13K0CKJH2nSV8,5147
|
|
11
|
+
gac/errors.py,sha256=pBq1nvHwv89KLvOGgap15IWmYTki2lghkkqyHpyVTzA,8035
|
|
12
|
+
gac/git.py,sha256=KuajV-4XywQ1uox_eB-CuoQ85xH_iJxsu3LcOVxLN7Y,13185
|
|
13
|
+
gac/git_state_validator.py,sha256=R_-Ee6umDDSqVnY_EXBO8uFvlpUWRGqRqHHgGO59p6g,7070
|
|
14
|
+
gac/grouped_commit_workflow.py,sha256=efjF_F2Vg8GF13asEhOGVgsa8U03ze6mcYqaq_meTNg,19278
|
|
15
|
+
gac/init_cli.py,sha256=99ga1qrFz9E-cpLLhI1c8FmvVa4BgXZMQK1cv13LM5M,2303
|
|
16
|
+
gac/interactive_mode.py,sha256=EwcqY39O-VKaRwmzT3IffQs8qLcq0dMeB4r5vBYVrnM,6397
|
|
17
|
+
gac/language_cli.py,sha256=3p4W3ezYjaJ2J5XvO1OOG0j-U_Ozla2-K2HMC-TURaQ,12906
|
|
18
|
+
gac/main.py,sha256=275I3vFLSZ4rEgte5DT_9UhdElWpe7tj0VQs93_dAu4,12142
|
|
19
|
+
gac/model_cli.py,sha256=dBJKW3uwkkc3OR57tOQbngk-k_Auau6C0RXE6HG4XAE,18346
|
|
20
|
+
gac/model_identifier.py,sha256=WKVxa31FI8ESRVmWvOLEviL6-t3ji7OGkOq6Dg48ZnM,2315
|
|
21
|
+
gac/oauth_retry.py,sha256=IFlz1KhBCwLWNSbluDBgw-07sEbFdwFvn-pO_kH4Eg8,5070
|
|
22
|
+
gac/postprocess.py,sha256=4cHWbu1PSWEW-1ct0X5i5So_NosxrXk_qC9vEBV7Z7c,4909
|
|
23
|
+
gac/preprocess.py,sha256=hk2p2X4-xVDvuy-T1VMzMa9k5fTUbhlWDyw89DCf81Q,15379
|
|
24
|
+
gac/prompt.py,sha256=Vkh2LSEUkl19z8UMSn8o7bl3uRBdIeDmVKyk9t4f-jI,16627
|
|
25
|
+
gac/prompt_builder.py,sha256=9VEIFGgYQUnnbRh9zrVjDmMGDr9v4Ij2V5NuEtI0cSw,3088
|
|
26
|
+
gac/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
gac/security.py,sha256=RYE3cik9c_zrqQYd0xIju8YUqZ1VPa2cVbktChuSyRg,9931
|
|
28
|
+
gac/utils.py,sha256=evJ0lSKLVjqKWoxvLfV4mBTBHTqaWlQzh591jdhTXcc,12689
|
|
29
|
+
gac/workflow_context.py,sha256=Vq1X2pXMkxgTeQSbkhARqBjwxA5THXlZ3OLrv49LXzo,3752
|
|
30
|
+
gac/workflow_utils.py,sha256=rGN7PqTqeUFLn260gm3hKyzF1PDVVuEsV1i2QHu2EO4,8118
|
|
31
|
+
gac/constants/__init__.py,sha256=un6JAvDggBoX95QD7G6xARQqe7nbtOoTuyA-xcobySE,1094
|
|
32
|
+
gac/constants/commit.py,sha256=z-ssDs1erhMgtq1VFDs9nIXb-8C17X-IdhwaqX5Ydok,1478
|
|
33
|
+
gac/constants/defaults.py,sha256=-VHk3XgV1H0lhHYXusw0CIP4rGvDqF6WmygSNTfV5ds,1301
|
|
34
|
+
gac/constants/file_patterns.py,sha256=eA-BHKYeM3mt_sNMmTVvk2nx1hZGTggtSnqiqiAA5Eg,3960
|
|
35
|
+
gac/constants/languages.py,sha256=UIqJ42WfzPQu_-flNf6YHBBI5MwNOlVeSN8cygJDiBA,3466
|
|
36
|
+
gac/oauth/__init__.py,sha256=wwfeIMGgpIAb8-ptLcSDyK_sM72HI1bkULyJm7BwVs8,614
|
|
37
|
+
gac/oauth/claude_code.py,sha256=KJEc-318aOKuyhQKjRYk8oyNqazhvnBU-rvM9CFNYKg,14092
|
|
38
|
+
gac/oauth/qwen_oauth.py,sha256=W-JCZYtCrhoDJUuGATLWrfxTs8fevd9Cj-x0RAriV5w,11151
|
|
39
|
+
gac/oauth/token_store.py,sha256=HW2sWKwkgyCuGCF5OwHaslH82s77hpFUcKCNQpWCD-8,2517
|
|
40
|
+
gac/providers/README.md,sha256=Vcep039sEqngYhxe18wM0rYpl_VccrRRrTqd9o8g3h4,12106
|
|
41
|
+
gac/providers/__init__.py,sha256=saJF1G2aHmOHzT7sWqXvoYy6c7gWbTB_AEYht7NeQkw,3111
|
|
42
|
+
gac/providers/anthropic.py,sha256=DgONlbKVHH8W4AlqPP-T4AmAxWADMMlqPAfi8GfhH7Q,535
|
|
43
|
+
gac/providers/azure_openai.py,sha256=t2D_r-OxzEy7Av2sRFFs5E_Zclsgk1o40UFuybtti08,2247
|
|
44
|
+
gac/providers/base.py,sha256=w42ILqRPuSJm5-NUmoYB4aY30apweNF4x-X6-Kkr3Jw,11138
|
|
45
|
+
gac/providers/cerebras.py,sha256=jz84u-ALqrYzCz13-FGBzPAhKdWJQ-Qw0KpuX1fuX7s,503
|
|
46
|
+
gac/providers/chutes.py,sha256=nLZBLL-E6qa6YePD_fvbXcI4nOA6L87lx7_292HPkDk,850
|
|
47
|
+
gac/providers/claude_code.py,sha256=-RY3v5xIdfS1UMkl7ZrGtHF678KXZ3eI-AeVusz3RC0,2926
|
|
48
|
+
gac/providers/custom_anthropic.py,sha256=jzZ4ep0BS14isDdmRJ7tqlArzUnJ4CIWEptuWG8X3yI,4360
|
|
49
|
+
gac/providers/custom_openai.py,sha256=11NOpTDG_k29bxnuACW7iXOhf-XKrTt1gxp9J1GBoy0,1578
|
|
50
|
+
gac/providers/deepseek.py,sha256=Zn1npn0DxgAQVHpTxhUn8XZPBBQNj9ajmJcX_Q6Xk28,498
|
|
51
|
+
gac/providers/error_handler.py,sha256=PcddgcgABLfK_pmODLkpwWSn4-aiptzTPn1D5DA9HqA,5640
|
|
52
|
+
gac/providers/fireworks.py,sha256=8ESmRldJDL3aOBMM68jTHvfyznjHOQKcOhhkTxGFwQo,516
|
|
53
|
+
gac/providers/gemini.py,sha256=ke8rshxGkcB9yVWN9qHmvTpDtFAGYaigpghxZt8q8Dw,3438
|
|
54
|
+
gac/providers/groq.py,sha256=rwqBHrM4SfZHVwXHpp9GPDYJozjSzjxj1Lc1WETY_NY,481
|
|
55
|
+
gac/providers/kimi_coding.py,sha256=TTB13J3s2Gp3dvr3SXafjdl2plF4uix2-bHB_DqQZSQ,1038
|
|
56
|
+
gac/providers/lmstudio.py,sha256=egGswgSgyJL4fBYz_L_zAgPsS9xj2dS8D5udzx_ihew,3054
|
|
57
|
+
gac/providers/minimax.py,sha256=rviAMgTdjQ5iSAXgmJKEf-kGrH5Wb-HFAydSjRkzq7Y,493
|
|
58
|
+
gac/providers/mistral.py,sha256=wp9j-uRWQT6oijGOBJumljuZQEUcF8aRhlw_TiVy2KY,491
|
|
59
|
+
gac/providers/moonshot.py,sha256=Q1HtSkRZFCJsVvrDETdojZgVBdB_A1gX5OZqIOHFnq0,496
|
|
60
|
+
gac/providers/ollama.py,sha256=O91Rmn-eptzTHKsbaiZAG3CpUYj2nGvsD6w54YcfLMw,2569
|
|
61
|
+
gac/providers/openai.py,sha256=giQSTxyNHvTxtBODENPTIc7ObdNtV5lu1uf7a3gkgSI,1216
|
|
62
|
+
gac/providers/openrouter.py,sha256=ShpF7ew6n2_7BSr9mqLHf1rG_V_ykrIjmaplbY4jZsk,779
|
|
63
|
+
gac/providers/protocol.py,sha256=QY474-0I8qOkMBxg4l_IoDgrT475OjdRv8pT4ckeAwA,1771
|
|
64
|
+
gac/providers/qwen.py,sha256=7Krb5c44A0yC0hI9JswGcEl--llhrjWypE6nDCdgX2Q,2398
|
|
65
|
+
gac/providers/registry.py,sha256=50BDPZcvbuqPwY98OTDCOIJjnhXHBBrWWCATKGT353s,1991
|
|
66
|
+
gac/providers/replicate.py,sha256=ISYe85kWX0RbHxmYWo3InZDOZsL3jZXUzq7YiEa_QKE,6402
|
|
67
|
+
gac/providers/streamlake.py,sha256=c2QWIvTGlxOHU5HkdS0bPdKLJIfGgHo2GAMfEQJA1dc,1117
|
|
68
|
+
gac/providers/synthetic.py,sha256=WBHQ6glxkndjPgvBoyG0oj24e-yun4aU6UqDtjll0E4,1535
|
|
69
|
+
gac/providers/together.py,sha256=ethi_6WhR6DTe3idZQXpXAeJOdEg_EefP5erAHDtS_A,501
|
|
70
|
+
gac/providers/zai.py,sha256=HSvpxE5uM4kE5zrs3pWHuer7LusRgWCDfYiN1R9sHSw,1010
|
|
71
|
+
gac/templates/__init__.py,sha256=lwaKKSWb21MUxEtYzUOJ3dHsfMgxZ_W60uR9aC6yMrs,50
|
|
72
|
+
gac/templates/question_generation.txt,sha256=nX-eOeW_hqofGXNJVLPxWMxNVxxV_21l25fqnAOJH9o,2868
|
|
73
|
+
gac/templates/system_prompt.txt,sha256=0eMkBTZVjxJDjutVpb5Sxif5QOhAtXWSSF3tNizI0S4,11076
|
|
74
|
+
gac/templates/user_prompt.txt,sha256=QF3bkOnAA5bKcqYnPEi1fHeHS41FWWQLLPRk0Q8YRqw,864
|
|
75
|
+
gac-3.10.10.dist-info/METADATA,sha256=4yUk_r17dJsWriEIxdICfpesJlF3CuC3DUZ9pZUe6Pk,11440
|
|
76
|
+
gac-3.10.10.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
77
|
+
gac-3.10.10.dist-info/entry_points.txt,sha256=tdjN-XMmcWfL92swuRAjT62bFLOAwk9bTMRLGP5Z4aI,36
|
|
78
|
+
gac-3.10.10.dist-info/licenses/LICENSE,sha256=vOab37NouL1PNs5BswnPayrMCqaN2sqLfMQfqPDrpZg,1103
|
|
79
|
+
gac-3.10.10.dist-info/RECORD,,
|