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.
Files changed (79) hide show
  1. gac/__init__.py +4 -6
  2. gac/__version__.py +1 -1
  3. gac/ai_utils.py +59 -43
  4. gac/auth_cli.py +181 -36
  5. gac/cli.py +26 -9
  6. gac/commit_executor.py +59 -0
  7. gac/config.py +81 -2
  8. gac/config_cli.py +19 -7
  9. gac/constants/__init__.py +34 -0
  10. gac/constants/commit.py +63 -0
  11. gac/constants/defaults.py +40 -0
  12. gac/constants/file_patterns.py +110 -0
  13. gac/constants/languages.py +119 -0
  14. gac/diff_cli.py +0 -22
  15. gac/errors.py +8 -2
  16. gac/git.py +6 -6
  17. gac/git_state_validator.py +193 -0
  18. gac/grouped_commit_workflow.py +458 -0
  19. gac/init_cli.py +2 -1
  20. gac/interactive_mode.py +179 -0
  21. gac/language_cli.py +0 -1
  22. gac/main.py +231 -926
  23. gac/model_cli.py +67 -11
  24. gac/model_identifier.py +70 -0
  25. gac/oauth/__init__.py +26 -0
  26. gac/oauth/claude_code.py +89 -22
  27. gac/oauth/qwen_oauth.py +327 -0
  28. gac/oauth/token_store.py +81 -0
  29. gac/oauth_retry.py +161 -0
  30. gac/postprocess.py +155 -0
  31. gac/prompt.py +21 -479
  32. gac/prompt_builder.py +88 -0
  33. gac/providers/README.md +437 -0
  34. gac/providers/__init__.py +70 -78
  35. gac/providers/anthropic.py +12 -46
  36. gac/providers/azure_openai.py +48 -88
  37. gac/providers/base.py +329 -0
  38. gac/providers/cerebras.py +10 -33
  39. gac/providers/chutes.py +16 -62
  40. gac/providers/claude_code.py +64 -87
  41. gac/providers/custom_anthropic.py +51 -81
  42. gac/providers/custom_openai.py +29 -83
  43. gac/providers/deepseek.py +10 -33
  44. gac/providers/error_handler.py +139 -0
  45. gac/providers/fireworks.py +10 -33
  46. gac/providers/gemini.py +66 -63
  47. gac/providers/groq.py +10 -58
  48. gac/providers/kimi_coding.py +19 -55
  49. gac/providers/lmstudio.py +64 -43
  50. gac/providers/minimax.py +10 -33
  51. gac/providers/mistral.py +10 -33
  52. gac/providers/moonshot.py +10 -33
  53. gac/providers/ollama.py +56 -33
  54. gac/providers/openai.py +30 -36
  55. gac/providers/openrouter.py +15 -52
  56. gac/providers/protocol.py +71 -0
  57. gac/providers/qwen.py +64 -0
  58. gac/providers/registry.py +58 -0
  59. gac/providers/replicate.py +140 -82
  60. gac/providers/streamlake.py +26 -46
  61. gac/providers/synthetic.py +35 -37
  62. gac/providers/together.py +10 -33
  63. gac/providers/zai.py +29 -57
  64. gac/py.typed +0 -0
  65. gac/security.py +1 -1
  66. gac/templates/__init__.py +1 -0
  67. gac/templates/question_generation.txt +60 -0
  68. gac/templates/system_prompt.txt +224 -0
  69. gac/templates/user_prompt.txt +28 -0
  70. gac/utils.py +36 -6
  71. gac/workflow_context.py +162 -0
  72. gac/workflow_utils.py +3 -8
  73. {gac-3.6.0.dist-info → gac-3.10.10.dist-info}/METADATA +6 -4
  74. gac-3.10.10.dist-info/RECORD +79 -0
  75. gac/constants.py +0 -321
  76. gac-3.6.0.dist-info/RECORD +0 -53
  77. {gac-3.6.0.dist-info → gac-3.10.10.dist-info}/WHEEL +0 -0
  78. {gac-3.6.0.dist-info → gac-3.10.10.dist-info}/entry_points.txt +0 -0
  79. {gac-3.6.0.dist-info → gac-3.10.10.dist-info}/licenses/LICENSE +0 -0
gac/postprocess.py ADDED
@@ -0,0 +1,155 @@
1
+ """Post-processing for AI-generated commit messages.
2
+
3
+ This module handles cleaning and normalization of commit messages generated
4
+ by AI models, removing artifacts like think tags, code blocks, and XML tags.
5
+ """
6
+
7
+ import re
8
+
9
+ from gac.constants import CommitMessageConstants
10
+
11
+
12
+ def _remove_think_tags(message: str) -> str:
13
+ """Remove AI reasoning <think> tags and their content from the message.
14
+
15
+ Args:
16
+ message: The message to clean
17
+
18
+ Returns:
19
+ Message with <think> tags removed
20
+ """
21
+ while re.search(r"<think>(?:(?!</think>)[^\n])*\n.*?</think>", message, flags=re.DOTALL | re.IGNORECASE):
22
+ message = re.sub(
23
+ r"<think>(?:(?!</think>)[^\n])*\n.*?</think>\s*", "", message, flags=re.DOTALL | re.IGNORECASE, count=1
24
+ )
25
+
26
+ message = re.sub(r"\n\n+\s*<think>.*?</think>\s*", "", message, flags=re.DOTALL | re.IGNORECASE)
27
+ message = re.sub(r"<think>.*?</think>\s*\n\n+", "", message, flags=re.DOTALL | re.IGNORECASE)
28
+
29
+ message = re.sub(r"<think>\s*\n.*$", "", message, flags=re.DOTALL | re.IGNORECASE)
30
+
31
+ conventional_prefixes_pattern = r"(" + "|".join(CommitMessageConstants.CONVENTIONAL_PREFIXES) + r")[\(:)]"
32
+ if re.search(r"^.*?</think>", message, flags=re.DOTALL | re.IGNORECASE):
33
+ prefix_match = re.search(conventional_prefixes_pattern, message, flags=re.IGNORECASE)
34
+ think_match = re.search(r"</think>", message, flags=re.IGNORECASE)
35
+
36
+ if not prefix_match or (think_match and think_match.start() < prefix_match.start()):
37
+ message = re.sub(r"^.*?</think>\s*", "", message, flags=re.DOTALL | re.IGNORECASE)
38
+
39
+ message = re.sub(r"</think>\s*$", "", message, flags=re.IGNORECASE)
40
+
41
+ return message
42
+
43
+
44
+ def _remove_code_blocks(message: str) -> str:
45
+ """Remove markdown code blocks from the message.
46
+
47
+ Args:
48
+ message: The message to clean
49
+
50
+ Returns:
51
+ Message with code blocks removed
52
+ """
53
+ return re.sub(r"```[\w]*\n|```", "", message)
54
+
55
+
56
+ def _extract_commit_from_reasoning(message: str) -> str:
57
+ """Extract the actual commit message from reasoning/preamble text.
58
+
59
+ Args:
60
+ message: The message potentially containing reasoning
61
+
62
+ Returns:
63
+ Extracted commit message
64
+ """
65
+ for indicator in CommitMessageConstants.COMMIT_INDICATORS:
66
+ if indicator.lower() in message.lower():
67
+ message = message.split(indicator, 1)[1].strip()
68
+ break
69
+
70
+ lines = message.split("\n")
71
+ for i, line in enumerate(lines):
72
+ if any(line.strip().startswith(f"{prefix}:") for prefix in CommitMessageConstants.CONVENTIONAL_PREFIXES):
73
+ message = "\n".join(lines[i:])
74
+ break
75
+
76
+ return message
77
+
78
+
79
+ def _remove_xml_tags(message: str) -> str:
80
+ """Remove XML tags that might have leaked into the message.
81
+
82
+ Args:
83
+ message: The message to clean
84
+
85
+ Returns:
86
+ Message with XML tags removed
87
+ """
88
+ for tag in CommitMessageConstants.XML_TAGS_TO_REMOVE:
89
+ message = message.replace(tag, "")
90
+ return message
91
+
92
+
93
+ def _fix_double_prefix(message: str) -> str:
94
+ """Fix double type prefix issues like 'chore: feat(scope):' to 'feat(scope):'.
95
+
96
+ Args:
97
+ message: The message to fix
98
+
99
+ Returns:
100
+ Message with double prefix corrected
101
+ """
102
+ double_prefix_pattern = re.compile(
103
+ r"^("
104
+ + r"|\s*".join(CommitMessageConstants.CONVENTIONAL_PREFIXES)
105
+ + r"):\s*("
106
+ + r"|\s*".join(CommitMessageConstants.CONVENTIONAL_PREFIXES)
107
+ + r")\(([^)]+)\):"
108
+ )
109
+ match = double_prefix_pattern.match(message)
110
+
111
+ if match:
112
+ second_type = match.group(2)
113
+ scope = match.group(3)
114
+ description = message[match.end() :].strip()
115
+ message = f"{second_type}({scope}): {description}"
116
+
117
+ return message
118
+
119
+
120
+ def _normalize_whitespace(message: str) -> str:
121
+ """Normalize whitespace, ensuring no more than one blank line between paragraphs.
122
+
123
+ Args:
124
+ message: The message to normalize
125
+
126
+ Returns:
127
+ Message with normalized whitespace
128
+ """
129
+ return re.sub(r"\n(?:[ \t]*\n){2,}", "\n\n", message).strip()
130
+
131
+
132
+ def clean_commit_message(message: str) -> str:
133
+ """Clean up a commit message generated by an AI model.
134
+
135
+ This function:
136
+ 1. Removes any preamble or reasoning text
137
+ 2. Removes code block markers and formatting
138
+ 3. Removes XML tags that might have leaked into the response
139
+ 4. Fixes double type prefix issues (e.g., "chore: feat(scope):")
140
+ 5. Normalizes whitespace
141
+
142
+ Args:
143
+ message: Raw commit message from AI
144
+
145
+ Returns:
146
+ Cleaned commit message ready for use
147
+ """
148
+ message = message.strip()
149
+ message = _remove_think_tags(message)
150
+ message = _remove_code_blocks(message)
151
+ message = _extract_commit_from_reasoning(message)
152
+ message = _remove_xml_tags(message)
153
+ message = _fix_double_prefix(message)
154
+ message = _normalize_whitespace(message)
155
+ return message