gac 3.10.3__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.

Files changed (67) hide show
  1. gac/__init__.py +15 -0
  2. gac/__version__.py +3 -0
  3. gac/ai.py +109 -0
  4. gac/ai_utils.py +246 -0
  5. gac/auth_cli.py +214 -0
  6. gac/cli.py +218 -0
  7. gac/commit_executor.py +62 -0
  8. gac/config.py +125 -0
  9. gac/config_cli.py +95 -0
  10. gac/constants.py +328 -0
  11. gac/diff_cli.py +159 -0
  12. gac/errors.py +231 -0
  13. gac/git.py +372 -0
  14. gac/git_state_validator.py +184 -0
  15. gac/grouped_commit_workflow.py +423 -0
  16. gac/init_cli.py +70 -0
  17. gac/interactive_mode.py +182 -0
  18. gac/language_cli.py +377 -0
  19. gac/main.py +476 -0
  20. gac/model_cli.py +430 -0
  21. gac/oauth/__init__.py +27 -0
  22. gac/oauth/claude_code.py +464 -0
  23. gac/oauth/qwen_oauth.py +327 -0
  24. gac/oauth/token_store.py +81 -0
  25. gac/preprocess.py +511 -0
  26. gac/prompt.py +878 -0
  27. gac/prompt_builder.py +88 -0
  28. gac/providers/README.md +437 -0
  29. gac/providers/__init__.py +80 -0
  30. gac/providers/anthropic.py +17 -0
  31. gac/providers/azure_openai.py +57 -0
  32. gac/providers/base.py +329 -0
  33. gac/providers/cerebras.py +15 -0
  34. gac/providers/chutes.py +25 -0
  35. gac/providers/claude_code.py +79 -0
  36. gac/providers/custom_anthropic.py +103 -0
  37. gac/providers/custom_openai.py +44 -0
  38. gac/providers/deepseek.py +15 -0
  39. gac/providers/error_handler.py +139 -0
  40. gac/providers/fireworks.py +15 -0
  41. gac/providers/gemini.py +90 -0
  42. gac/providers/groq.py +15 -0
  43. gac/providers/kimi_coding.py +27 -0
  44. gac/providers/lmstudio.py +80 -0
  45. gac/providers/minimax.py +15 -0
  46. gac/providers/mistral.py +15 -0
  47. gac/providers/moonshot.py +15 -0
  48. gac/providers/ollama.py +73 -0
  49. gac/providers/openai.py +32 -0
  50. gac/providers/openrouter.py +21 -0
  51. gac/providers/protocol.py +71 -0
  52. gac/providers/qwen.py +64 -0
  53. gac/providers/registry.py +58 -0
  54. gac/providers/replicate.py +156 -0
  55. gac/providers/streamlake.py +31 -0
  56. gac/providers/synthetic.py +40 -0
  57. gac/providers/together.py +15 -0
  58. gac/providers/zai.py +31 -0
  59. gac/py.typed +0 -0
  60. gac/security.py +293 -0
  61. gac/utils.py +401 -0
  62. gac/workflow_utils.py +217 -0
  63. gac-3.10.3.dist-info/METADATA +283 -0
  64. gac-3.10.3.dist-info/RECORD +67 -0
  65. gac-3.10.3.dist-info/WHEEL +4 -0
  66. gac-3.10.3.dist-info/entry_points.txt +2 -0
  67. gac-3.10.3.dist-info/licenses/LICENSE +16 -0
gac/workflow_utils.py ADDED
@@ -0,0 +1,217 @@
1
+ import logging
2
+ import tempfile
3
+ from pathlib import Path
4
+
5
+ import click
6
+ from prompt_toolkit import prompt
7
+ from rich.console import Console
8
+ from rich.panel import Panel
9
+
10
+ from gac.constants import EnvDefaults
11
+
12
+ logger = logging.getLogger(__name__)
13
+ console = Console()
14
+
15
+
16
+ def handle_confirmation_loop(
17
+ commit_message: str,
18
+ conversation_messages: list[dict[str, str]],
19
+ quiet: bool,
20
+ model: str,
21
+ ) -> tuple[str, str, list[dict[str, str]]]:
22
+ from gac.utils import edit_commit_message_inplace
23
+
24
+ while True:
25
+ response = click.prompt(
26
+ "Proceed with commit above? [y/n/r/e/<feedback>]",
27
+ type=str,
28
+ show_default=False,
29
+ ).strip()
30
+ response_lower = response.lower()
31
+
32
+ if response_lower in ["y", "yes"]:
33
+ return ("yes", commit_message, conversation_messages)
34
+ if response_lower in ["n", "no"]:
35
+ return ("no", commit_message, conversation_messages)
36
+ if response == "":
37
+ continue
38
+ if response_lower in ["e", "edit"]:
39
+ edited_message = edit_commit_message_inplace(commit_message)
40
+ if edited_message:
41
+ commit_message = edited_message
42
+ conversation_messages[-1] = {"role": "assistant", "content": commit_message}
43
+ logger.info("Commit message edited by user")
44
+ console.print("\n[bold green]Edited commit message:[/bold green]")
45
+ console.print(Panel(commit_message, title="Commit Message", border_style="cyan"))
46
+ else:
47
+ console.print("[yellow]Using previous message.[/yellow]")
48
+ console.print(Panel(commit_message, title="Commit Message", border_style="cyan"))
49
+ continue
50
+ if response_lower in ["r", "reroll"]:
51
+ msg = "Please provide an alternative commit message using the same repository context."
52
+ conversation_messages.append({"role": "user", "content": msg})
53
+ console.print("[cyan]Regenerating commit message...[/cyan]")
54
+ return ("regenerate", commit_message, conversation_messages)
55
+
56
+ msg = f"Please revise the commit message based on this feedback: {response}"
57
+ conversation_messages.append({"role": "user", "content": msg})
58
+ console.print(f"[cyan]Regenerating commit message with feedback: {response}[/cyan]")
59
+ return ("regenerate", commit_message, conversation_messages)
60
+
61
+
62
+ def execute_commit(commit_message: str, no_verify: bool, hook_timeout: int | None = None) -> None:
63
+ from gac.git import run_git_command
64
+
65
+ commit_args = ["commit", "-m", commit_message]
66
+ if no_verify:
67
+ commit_args.append("--no-verify")
68
+ effective_timeout = hook_timeout if hook_timeout and hook_timeout > 0 else EnvDefaults.HOOK_TIMEOUT
69
+ run_git_command(commit_args, timeout=effective_timeout)
70
+ logger.info("Commit created successfully")
71
+ console.print("[green]Commit created successfully[/green]")
72
+
73
+
74
+ def check_token_warning(
75
+ prompt_tokens: int,
76
+ warning_limit: int,
77
+ require_confirmation: bool,
78
+ ) -> bool:
79
+ if warning_limit and prompt_tokens > warning_limit:
80
+ console.print(
81
+ f"[yellow]⚠️ WARNING: Prompt has {prompt_tokens} tokens (warning threshold: {warning_limit})[/yellow]"
82
+ )
83
+ if require_confirmation:
84
+ proceed = click.confirm("Do you want to continue anyway?", default=True)
85
+ if not proceed:
86
+ console.print("[yellow]Aborted due to large token count.[/yellow]")
87
+ return False
88
+ return True
89
+
90
+
91
+ def display_commit_message(commit_message: str, prompt_tokens: int, model: str, quiet: bool) -> None:
92
+ from gac.ai_utils import count_tokens
93
+
94
+ console.print("[bold green]Generated commit message:[/bold green]")
95
+ console.print(Panel(commit_message, title="Commit Message", border_style="cyan"))
96
+
97
+ if not quiet:
98
+ completion_tokens = count_tokens(commit_message, model)
99
+ total_tokens = prompt_tokens + completion_tokens
100
+ console.print(
101
+ f"[dim]Token usage: {prompt_tokens} prompt + {completion_tokens} completion = {total_tokens} total[/dim]"
102
+ )
103
+
104
+
105
+ def restore_staging(staged_files: list[str], staged_diff: str | None = None) -> None:
106
+ """Restore the git staging area to a previous state.
107
+
108
+ Args:
109
+ staged_files: List of file paths that should be staged
110
+ staged_diff: Optional staged diff to reapply for partial staging
111
+ """
112
+ from gac.git import run_git_command
113
+
114
+ run_git_command(["reset", "HEAD"])
115
+
116
+ if staged_diff:
117
+ temp_path: Path | None = None
118
+ try:
119
+ with tempfile.NamedTemporaryFile("w", delete=False) as tmp:
120
+ tmp.write(staged_diff)
121
+ temp_path = Path(tmp.name)
122
+ run_git_command(["apply", "--cached", str(temp_path)])
123
+ return
124
+ except Exception as e:
125
+ logger.warning(f"Failed to reapply staged diff, falling back to file list: {e}")
126
+ finally:
127
+ if temp_path:
128
+ temp_path.unlink(missing_ok=True)
129
+
130
+ for file_path in staged_files:
131
+ try:
132
+ run_git_command(["add", file_path])
133
+ except Exception as e:
134
+ logger.warning(f"Failed to restore staging for {file_path}: {e}")
135
+
136
+
137
+ def collect_interactive_answers(questions: list[str]) -> dict[str, str] | None:
138
+ """Collect user answers to generated questions interactively.
139
+
140
+ Args:
141
+ questions: List of generated questions
142
+
143
+ Returns:
144
+ Dictionary mapping questions to answers, or None if user aborted
145
+ """
146
+ if not questions:
147
+ return {}
148
+
149
+ console.print("\n[bold cyan]🤝 Let's clarify your commit intent:[/bold cyan]")
150
+ console.print("[dim]Answer each question, press Enter to skip, or type:[/dim]")
151
+ console.print("[dim] • 'skip' - skip remaining questions[/dim]")
152
+ console.print("[dim] • 'quit' - abort interactive mode[/dim]\n")
153
+
154
+ answers = {}
155
+
156
+ for i, question in enumerate(questions, 1):
157
+ # Display the question with nice formatting
158
+ console.print(f"[bold blue]Question {i}:[/bold blue] {question}")
159
+
160
+ try:
161
+ answer = prompt("Your answer: ").strip()
162
+
163
+ # Handle special commands
164
+ answer_lower = answer.lower()
165
+
166
+ if answer_lower == "quit":
167
+ console.print("\n[yellow]⚠️ Interactive mode aborted by user[/yellow]")
168
+ return None
169
+ elif answer_lower == "skip":
170
+ console.print("[dim]Skipping remaining questions...[/dim]")
171
+ break
172
+ elif answer_lower == "" or answer_lower == "none":
173
+ # User explicitly skipped this question
174
+ console.print("[dim]↳ Skipped[/dim]")
175
+ continue
176
+ else:
177
+ # Valid answer provided
178
+ answers[question] = answer
179
+ console.print("[dim]↳ Got it![/dim]")
180
+
181
+ except KeyboardInterrupt:
182
+ # User pressed Ctrl+C
183
+ console.print("\n[yellow]⚠️ Interactive mode aborted by user[/yellow]")
184
+ return None
185
+
186
+ console.print() # Add spacing between questions
187
+
188
+ return answers
189
+
190
+
191
+ def format_answers_for_prompt(answers: dict[str, str]) -> str:
192
+ """Format collected answers for inclusion in the commit message prompt.
193
+
194
+ Args:
195
+ answers: Dictionary mapping questions to answers
196
+
197
+ Returns:
198
+ Formatted string for inclusion in the prompt
199
+ """
200
+ if not answers:
201
+ return ""
202
+
203
+ formatted_lines = []
204
+ for question, answer in answers.items():
205
+ formatted_lines.append(f"Q: {question}")
206
+ formatted_lines.append(f"A: {answer}")
207
+ formatted_lines.append("")
208
+
209
+ answers_text = "\n".join(formatted_lines).rstrip()
210
+
211
+ return (
212
+ f"\n\n<user_answers>\n"
213
+ f"The user provided the following clarifying information:\n\n"
214
+ f"{answers_text}\n\n"
215
+ f"</user_answers>\n\n"
216
+ f"<context_request>Use the user's answers above to craft a more accurate and informative commit message that captures their specific intent and context.</context_request>"
217
+ )
@@ -0,0 +1,283 @@
1
+ Metadata-Version: 2.4
2
+ Name: gac
3
+ Version: 3.10.3
4
+ Summary: LLM-powered Git commit message generator with multi-provider support
5
+ Project-URL: Homepage, https://github.com/cellwebb/gac
6
+ Project-URL: Documentation, https://github.com/cellwebb/gac#readme
7
+ Project-URL: Repository, https://github.com/cellwebb/gac.git
8
+ Project-URL: Issues, https://github.com/cellwebb/gac/issues
9
+ Project-URL: Changelog, https://github.com/cellwebb/gac/blob/main/CHANGELOG.md
10
+ Project-URL: Source, https://github.com/cellwebb/gac
11
+ Author-email: cellwebb <cellwebb@users.noreply.github.com>
12
+ License-Expression: MIT
13
+ License-File: LICENSE
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Programming Language :: Python :: Implementation :: CPython
22
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: click>=8.3.0
25
+ Requires-Dist: httpcore>=1.0.9
26
+ Requires-Dist: httpx>=0.28.0
27
+ Requires-Dist: prompt-toolkit>=3.0.36
28
+ Requires-Dist: pydantic>=2.12.0
29
+ Requires-Dist: python-dotenv>=1.1.1
30
+ Requires-Dist: questionary
31
+ Requires-Dist: rich>=14.1.0
32
+ Requires-Dist: tiktoken>=0.12.0
33
+ Provides-Extra: dev
34
+ Requires-Dist: build; extra == 'dev'
35
+ Requires-Dist: codecov; extra == 'dev'
36
+ Requires-Dist: pytest; extra == 'dev'
37
+ Requires-Dist: pytest-cov; extra == 'dev'
38
+ Requires-Dist: ruff; extra == 'dev'
39
+ Requires-Dist: twine; extra == 'dev'
40
+ Description-Content-Type: text/markdown
41
+
42
+ <!-- markdownlint-disable MD013 -->
43
+ <!-- markdownlint-disable MD033 MD036 -->
44
+
45
+ <div align="center">
46
+
47
+ # 🚀 Git Auto Commit (gac)
48
+
49
+ [![PyPI version](https://img.shields.io/pypi/v/gac.svg)](https://pypi.org/project/gac/)
50
+ [![Python](https://img.shields.io/badge/python-3.10--3.14-blue.svg)](https://www.python.org/downloads/)
51
+ [![Build Status](https://github.com/cellwebb/gac/actions/workflows/ci.yml/badge.svg)](https://github.com/cellwebb/gac/actions)
52
+ [![codecov](https://codecov.io/gh/cellwebb/gac/branch/main/graph/badge.svg)](https://app.codecov.io/gh/cellwebb/gac)
53
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
54
+ [![mypy](https://img.shields.io/badge/mypy-checked-blue.svg)](https://mypy-lang.org/)
55
+ [![Contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg)](docs/en/CONTRIBUTING.md)
56
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
57
+
58
+ **English** | [简体中文](docs/zh-CN/README.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja/README.md) | [한국어](docs/ko/README.md) | [हिन्दी](docs/hi/README.md) | [Tiếng Việt](docs/vi/README.md) | [Français](docs/fr/README.md) | [Русский](docs/ru/README.md) | [Español](docs/es/README.md) | [Português](docs/pt/README.md) | [Norsk](docs/no/README.md) | [Svenska](docs/sv/README.md) | [Deutsch](docs/de/README.md) | [Nederlands](docs/nl/README.md) | [Italiano](docs/it/README.md)
59
+
60
+ **LLM-powered commit messages that understand your code!**
61
+
62
+ **Automate your commits!** Replace `git commit -m "..."` with `gac` for contextual, well-formatted commit messages generated by large language models!
63
+
64
+ ---
65
+
66
+ ## What You Get
67
+
68
+ Intelligent, contextual messages that explain the **why** behind your changes:
69
+
70
+ ![GAC generating a contextual commit message](assets/gac-simple-usage.png)
71
+
72
+ ---
73
+
74
+ </div>
75
+
76
+ <!-- markdownlint-enable MD033 MD036 -->
77
+
78
+ ## Quick Start
79
+
80
+ ### Use gac without installing
81
+
82
+ ```bash
83
+ uvx gac init # Configure your provider, model, and language
84
+ uvx gac # Generate and commit with LLM
85
+ ```
86
+
87
+ That's it! Review the generated message and confirm with `y`.
88
+
89
+ ### Install and use gac
90
+
91
+ ```bash
92
+ uv tool install gac
93
+ gac init
94
+ gac
95
+ ```
96
+
97
+ ### Upgrade installed gac
98
+
99
+ ```bash
100
+ uv tool upgrade gac
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Key Features
106
+
107
+ ### 🌐 **25+ Supported Providers**
108
+
109
+ - **Anthropic** • **Azure OpenAI** • **Cerebras** • **Chutes.ai** • **Claude Code (OAuth)**
110
+ - **DeepSeek** • **Fireworks** • **Gemini** • **Groq** • **Kimi for Coding** • **LM Studio**
111
+ - **MiniMax.io** • **Mistral AI** • **Moonshot AI** • **Ollama** • **OpenAI** • **OpenRouter**
112
+ - **Qwen.ai (OAuth)** • **Replicate** • **Streamlake** • **Synthetic.new** • **Together AI**
113
+ - **Z.AI** • **Z.AI Coding** • **Custom Endpoints (Anthropic/OpenAI)**
114
+
115
+ ### 🧠 **Smart LLM Analysis**
116
+
117
+ - **Understands intent**: Analyzes code structure, logic, and patterns to understand the "why" behind your changes, not just what changed
118
+ - **Semantic awareness**: Recognizes refactoring, bug fixes, features, and breaking changes to generate contextually appropriate messages
119
+ - **Intelligent filtering**: Prioritizes meaningful changes while ignoring generated files, dependencies, and artifacts
120
+ - **Intelligent commit grouping** - Automatically group related changes into multiple logical commits with `--group`
121
+
122
+ ### 📝 **Multiple Message Formats**
123
+
124
+ - **One-liner** (-o flag): Single-line commit message following conventional commit format
125
+ - **Standard** (default): Summary with bullet points explaining implementation details
126
+ - **Verbose** (-v flag): Comprehensive explanations including motivation, technical approach, and impact analysis
127
+
128
+ ### 🌍 **Multilingual Support**
129
+
130
+ - **25+ languages**: Generate commit messages in English, Chinese, Japanese, Korean, Spanish, French, German, and 20+ more languages
131
+ - **Flexible translation**: Choose to keep conventional commit prefixes in English for tool compatibility, or fully translate them
132
+ - **Multiple workflows**: Set a default language with `gac language`, or use `-l <language>` flag for one-time overrides
133
+ - **Native script support**: Full support for non-Latin scripts including CJK, Cyrillic, Thai, and more
134
+
135
+ ### 💻 **Developer Experience**
136
+
137
+ - **Interactive feedback**: Type `r` to reroll, `e` to edit in-place with vi/emacs keybindings, or directly type your feedback like `make it shorter` or `focus on the bug fix`
138
+ - **Interactive questioning**: Use `--interactive` (`-i`) to answer targeted questions about your changes for more contextual commit messages
139
+ - **One-command workflows**: Complete workflows with flags like `gac -ayp` (stage all, auto-confirm, push)
140
+ - **Git integration**: Respects pre-commit and lefthook hooks, running them before expensive LLM operations
141
+
142
+ ### 🛡️ **Built-in Security**
143
+
144
+ - **Automatic secret detection**: Scans for API keys, passwords, and tokens before committing
145
+ - **Interactive protection**: Prompts before committing potentially sensitive data with clear remediation options
146
+ - **Smart filtering**: Ignores example files, template files, and placeholder text to reduce false positives
147
+
148
+ ---
149
+
150
+ ## Usage Examples
151
+
152
+ ### Basic Workflow
153
+
154
+ ```bash
155
+ # Stage your changes
156
+ git add .
157
+
158
+ # Generate and commit with LLM
159
+ gac
160
+
161
+ # Review → y (commit) | n (cancel) | r (reroll) | e (edit) | or type feedback
162
+ ```
163
+
164
+ ### Common Commands
165
+
166
+ | Command | Description |
167
+ | --------------- | ----------------------------------------------------------------------- |
168
+ | `gac` | Generate commit message |
169
+ | `gac -y` | Auto-confirm (no review needed) |
170
+ | `gac -a` | Stage all before generating commit message |
171
+ | `gac -o` | One-line message for trivial changes |
172
+ | `gac -v` | Verbose format with Motivation, Technical Approach, and Impact Analysis |
173
+ | `gac -h "hint"` | Add context for LLM (e.g., `gac -h "bug fix"`) |
174
+ | `gac -s` | Include scope (e.g., feat(auth):) |
175
+ | `gac -i` | Ask questions about changes for better context |
176
+ | `gac -p` | Commit and push |
177
+
178
+ ### Power User Examples
179
+
180
+ ```bash
181
+ # Complete workflow in one command
182
+ gac -ayp -h "release preparation"
183
+
184
+ # Detailed explanation with scope
185
+ gac -v -s
186
+
187
+ # Quick one-liner for small changes
188
+ gac -o
189
+
190
+ # Group changes into logically related commits
191
+ gac -ag
192
+
193
+ # Interactive mode with verbose output for detailed explanations
194
+ gac -iv
195
+
196
+ # Debug what the LLM sees
197
+ gac --show-prompt
198
+
199
+ # Skip security scan (use carefully)
200
+ gac --skip-secret-scan
201
+ ```
202
+
203
+ ### Interactive Feedback System
204
+
205
+ Not happy with the result? You have several options:
206
+
207
+ ```bash
208
+ # Simple reroll (no feedback)
209
+ r
210
+
211
+ # Edit in-place with rich terminal editing
212
+ e
213
+ # Uses prompt_toolkit for multi-line editing with vi/emacs keybindings
214
+ # Press Esc+Enter or Ctrl+S to submit, Ctrl+C to cancel
215
+
216
+ # Or just type your feedback directly!
217
+ make it shorter and focus on the performance improvement
218
+ use conventional commit format with scope
219
+ explain the security implications
220
+
221
+ # Press Enter on empty input to see the prompt again
222
+ ```
223
+
224
+ The edit feature (`e`) provides rich in-place terminal editing, allowing you to:
225
+
226
+ - **Edit naturally**: Multi-line editing with familiar vi/emacs key bindings
227
+ - **Make quick fixes**: Correct typos, adjust wording, or refine formatting
228
+ - **Add details**: Include information the LLM might have missed
229
+ - **Restructure**: Reorganize bullet points or change the message structure
230
+
231
+ ---
232
+
233
+ ## Configuration
234
+
235
+ Run `gac init` to configure your provider interactively, or set environment variables:
236
+
237
+ Need to change providers or models later without touching language settings? Use `gac model` for a streamlined flow that skips the language prompts.
238
+
239
+ ```bash
240
+ # Example configuration
241
+ GAC_MODEL=anthropic:your-model-name
242
+ OPENAI_API_KEY=your_key_here
243
+ ANTHROPIC_API_KEY=your_key_here
244
+ ```
245
+
246
+ See `.gac.env.example` for all available options.
247
+
248
+ **Want commit messages in another language?** Run `gac language` to select from 25+ languages including Español, Français, 日本語, and more.
249
+
250
+ **Want to customize commit message style?** See [docs/CUSTOM_SYSTEM_PROMPTS.md](docs/en/CUSTOM_SYSTEM_PROMPTS.md) for guidance on writing custom system prompts.
251
+
252
+ ---
253
+
254
+ ## Project Analytics
255
+
256
+ 📊 **[View live usage analytics and statistics →](https://clickpy.clickhouse.com/dashboard/gac)**
257
+
258
+ Track real-time installation metrics and package download statistics.
259
+
260
+ ---
261
+
262
+ ## Getting Help
263
+
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
267
+ - **Custom prompts**: [docs/CUSTOM_SYSTEM_PROMPTS.md](docs/en/CUSTOM_SYSTEM_PROMPTS.md) - Customize commit message style
268
+ - **Troubleshooting**: [docs/TROUBLESHOOTING.md](docs/en/TROUBLESHOOTING.md) - Common issues and solutions
269
+ - **Contributing**: [docs/CONTRIBUTING.md](docs/en/CONTRIBUTING.md) - Development setup and guidelines
270
+
271
+ ---
272
+
273
+ <!-- markdownlint-disable MD033 MD036 -->
274
+
275
+ <div align="center">
276
+
277
+ Made with ❤️ for developers who want better commit messages
278
+
279
+ [⭐ Star us on GitHub](https://github.com/cellwebb/gac) • [🐛 Report issues](https://github.com/cellwebb/gac/issues) • [📖 Full docs](docs/en/USAGE.md)
280
+
281
+ </div>
282
+
283
+ <!-- markdownlint-enable MD033 MD036 -->
@@ -0,0 +1,67 @@
1
+ gac/__init__.py,sha256=z9yGInqtycFIT3g1ca24r-A3699hKVaRqGUI79wsmMc,415
2
+ gac/__version__.py,sha256=5XVP0Fecvo1AJCr8W04GCVQs6iHzFQ_bgMDU2dh8eYE,67
3
+ gac/ai.py,sha256=HnXmRFmUJin5k755iBqSLgKYssjShjKXz9SwICEpMag,3835
4
+ gac/ai_utils.py,sha256=jScTeAAIA3VNdTaNFUEPTbwPbYTmlsppIM5GWiURMMQ,9931
5
+ gac/auth_cli.py,sha256=D1UcpOdyLqnKNJQTBq2lHCHBaxFZsRbM4Krvg-1-NfA,6822
6
+ gac/cli.py,sha256=3IZgS4xzt96YrfMT7wwD1xvHH4fPpVn6h8dUokFUal8,7998
7
+ gac/commit_executor.py,sha256=idbTv13Igl1P6935ApsWS7h0xhvqnnmP2-fe1W-5_1M,2422
8
+ gac/config.py,sha256=qaQ7-udCA0Gb-S8aKEGM40ywVWQyMPtTpnBPq3BTkhg,5208
9
+ gac/config_cli.py,sha256=6tUoi-Xcexv5i2Y6p-wobrYlzeH2DNxlHMkyhFnFBYk,2994
10
+ gac/constants.py,sha256=ckzm2yM2-DA_98TRpetX5mzQ28TqJPGtm0cEZnRj_A8,9958
11
+ gac/diff_cli.py,sha256=roBnoPcMn58rMGA475lqXlC2iYERC-13K0CKJH2nSV8,5147
12
+ gac/errors.py,sha256=tJECzn_IdYn3c9zXmq3SapFuQkXnh5Z2W-Bh1hEZZxU,7931
13
+ gac/git.py,sha256=KuajV-4XywQ1uox_eB-CuoQ85xH_iJxsu3LcOVxLN7Y,13185
14
+ gac/git_state_validator.py,sha256=pzTcs0upUoXd5tb84h24jpM9pRfjD9roKCq23NAKuQQ,6845
15
+ gac/grouped_commit_workflow.py,sha256=tA0mkyr0i0UzbkMTdBC-ALMWqSnqhmaRkNwY6-sif2Q,18065
16
+ gac/init_cli.py,sha256=99ga1qrFz9E-cpLLhI1c8FmvVa4BgXZMQK1cv13LM5M,2303
17
+ gac/interactive_mode.py,sha256=oebLslCdXt8lmMZHvrgp462-62IoKbwug8QnTc3onFQ,6501
18
+ gac/language_cli.py,sha256=3p4W3ezYjaJ2J5XvO1OOG0j-U_Ozla2-K2HMC-TURaQ,12906
19
+ gac/main.py,sha256=aWcYKsbhzD_zwljLNe508atD2hGMDB4CehBZN8jUpss,17055
20
+ gac/model_cli.py,sha256=dBJKW3uwkkc3OR57tOQbngk-k_Auau6C0RXE6HG4XAE,18346
21
+ gac/preprocess.py,sha256=hk2p2X4-xVDvuy-T1VMzMa9k5fTUbhlWDyw89DCf81Q,15379
22
+ gac/prompt.py,sha256=6YpJT89lI8v0dVuWUIeoQAaxn9Q3P7rPuTA4W51NlX4,35770
23
+ gac/prompt_builder.py,sha256=9VEIFGgYQUnnbRh9zrVjDmMGDr9v4Ij2V5NuEtI0cSw,3088
24
+ gac/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ gac/security.py,sha256=RYE3cik9c_zrqQYd0xIju8YUqZ1VPa2cVbktChuSyRg,9931
26
+ gac/utils.py,sha256=evJ0lSKLVjqKWoxvLfV4mBTBHTqaWlQzh591jdhTXcc,12689
27
+ gac/workflow_utils.py,sha256=rGN7PqTqeUFLn260gm3hKyzF1PDVVuEsV1i2QHu2EO4,8118
28
+ gac/oauth/__init__.py,sha256=wwfeIMGgpIAb8-ptLcSDyK_sM72HI1bkULyJm7BwVs8,614
29
+ gac/oauth/claude_code.py,sha256=KJEc-318aOKuyhQKjRYk8oyNqazhvnBU-rvM9CFNYKg,14092
30
+ gac/oauth/qwen_oauth.py,sha256=W-JCZYtCrhoDJUuGATLWrfxTs8fevd9Cj-x0RAriV5w,11151
31
+ gac/oauth/token_store.py,sha256=HW2sWKwkgyCuGCF5OwHaslH82s77hpFUcKCNQpWCD-8,2517
32
+ gac/providers/README.md,sha256=Vcep039sEqngYhxe18wM0rYpl_VccrRRrTqd9o8g3h4,12106
33
+ gac/providers/__init__.py,sha256=saJF1G2aHmOHzT7sWqXvoYy6c7gWbTB_AEYht7NeQkw,3111
34
+ gac/providers/anthropic.py,sha256=DgONlbKVHH8W4AlqPP-T4AmAxWADMMlqPAfi8GfhH7Q,535
35
+ gac/providers/azure_openai.py,sha256=t2D_r-OxzEy7Av2sRFFs5E_Zclsgk1o40UFuybtti08,2247
36
+ gac/providers/base.py,sha256=w42ILqRPuSJm5-NUmoYB4aY30apweNF4x-X6-Kkr3Jw,11138
37
+ gac/providers/cerebras.py,sha256=jz84u-ALqrYzCz13-FGBzPAhKdWJQ-Qw0KpuX1fuX7s,503
38
+ gac/providers/chutes.py,sha256=nLZBLL-E6qa6YePD_fvbXcI4nOA6L87lx7_292HPkDk,850
39
+ gac/providers/claude_code.py,sha256=-RY3v5xIdfS1UMkl7ZrGtHF678KXZ3eI-AeVusz3RC0,2926
40
+ gac/providers/custom_anthropic.py,sha256=jzZ4ep0BS14isDdmRJ7tqlArzUnJ4CIWEptuWG8X3yI,4360
41
+ gac/providers/custom_openai.py,sha256=11NOpTDG_k29bxnuACW7iXOhf-XKrTt1gxp9J1GBoy0,1578
42
+ gac/providers/deepseek.py,sha256=Zn1npn0DxgAQVHpTxhUn8XZPBBQNj9ajmJcX_Q6Xk28,498
43
+ gac/providers/error_handler.py,sha256=PcddgcgABLfK_pmODLkpwWSn4-aiptzTPn1D5DA9HqA,5640
44
+ gac/providers/fireworks.py,sha256=8ESmRldJDL3aOBMM68jTHvfyznjHOQKcOhhkTxGFwQo,516
45
+ gac/providers/gemini.py,sha256=ke8rshxGkcB9yVWN9qHmvTpDtFAGYaigpghxZt8q8Dw,3438
46
+ gac/providers/groq.py,sha256=rwqBHrM4SfZHVwXHpp9GPDYJozjSzjxj1Lc1WETY_NY,481
47
+ gac/providers/kimi_coding.py,sha256=TTB13J3s2Gp3dvr3SXafjdl2plF4uix2-bHB_DqQZSQ,1038
48
+ gac/providers/lmstudio.py,sha256=egGswgSgyJL4fBYz_L_zAgPsS9xj2dS8D5udzx_ihew,3054
49
+ gac/providers/minimax.py,sha256=rviAMgTdjQ5iSAXgmJKEf-kGrH5Wb-HFAydSjRkzq7Y,493
50
+ gac/providers/mistral.py,sha256=wp9j-uRWQT6oijGOBJumljuZQEUcF8aRhlw_TiVy2KY,491
51
+ gac/providers/moonshot.py,sha256=Q1HtSkRZFCJsVvrDETdojZgVBdB_A1gX5OZqIOHFnq0,496
52
+ gac/providers/ollama.py,sha256=O91Rmn-eptzTHKsbaiZAG3CpUYj2nGvsD6w54YcfLMw,2569
53
+ gac/providers/openai.py,sha256=giQSTxyNHvTxtBODENPTIc7ObdNtV5lu1uf7a3gkgSI,1216
54
+ gac/providers/openrouter.py,sha256=ShpF7ew6n2_7BSr9mqLHf1rG_V_ykrIjmaplbY4jZsk,779
55
+ gac/providers/protocol.py,sha256=QY474-0I8qOkMBxg4l_IoDgrT475OjdRv8pT4ckeAwA,1771
56
+ gac/providers/qwen.py,sha256=7Krb5c44A0yC0hI9JswGcEl--llhrjWypE6nDCdgX2Q,2398
57
+ gac/providers/registry.py,sha256=50BDPZcvbuqPwY98OTDCOIJjnhXHBBrWWCATKGT353s,1991
58
+ gac/providers/replicate.py,sha256=ISYe85kWX0RbHxmYWo3InZDOZsL3jZXUzq7YiEa_QKE,6402
59
+ gac/providers/streamlake.py,sha256=c2QWIvTGlxOHU5HkdS0bPdKLJIfGgHo2GAMfEQJA1dc,1117
60
+ gac/providers/synthetic.py,sha256=WBHQ6glxkndjPgvBoyG0oj24e-yun4aU6UqDtjll0E4,1535
61
+ gac/providers/together.py,sha256=ethi_6WhR6DTe3idZQXpXAeJOdEg_EefP5erAHDtS_A,501
62
+ gac/providers/zai.py,sha256=HSvpxE5uM4kE5zrs3pWHuer7LusRgWCDfYiN1R9sHSw,1010
63
+ gac-3.10.3.dist-info/METADATA,sha256=X5A4nx4J4TENcDQZOLPLyd8ieiOswP_zcj4pkOjBADk,11439
64
+ gac-3.10.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
65
+ gac-3.10.3.dist-info/entry_points.txt,sha256=tdjN-XMmcWfL92swuRAjT62bFLOAwk9bTMRLGP5Z4aI,36
66
+ gac-3.10.3.dist-info/licenses/LICENSE,sha256=vOab37NouL1PNs5BswnPayrMCqaN2sqLfMQfqPDrpZg,1103
67
+ gac-3.10.3.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ gac = gac.cli:cli
@@ -0,0 +1,16 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2025 cellwebb <cellwebb@users.noreply.github.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ persons to whom the Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.