acm-cli 0.1.0__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.
acm/ui.py ADDED
@@ -0,0 +1,279 @@
1
+ """终端 UI 模块:使用 rich 库实现彩色输出、spinner、diff 预览、交互菜单。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ import queue
6
+ import time
7
+ from dataclasses import dataclass
8
+ from threading import Thread
9
+ from typing import Generator, Union
10
+
11
+ import click
12
+ from rich.console import Console
13
+ from rich.live import Live
14
+ from rich.panel import Panel
15
+ from rich.text import Text
16
+ from acm.git import DiffResult, FileChange
17
+ from acm.splitter import CommitGroup
18
+
19
+ console = Console()
20
+ err_console = Console(stderr=True)
21
+
22
+
23
+ # ---------------------------------------------------------------------------
24
+ # 错误与信息输出
25
+ # ---------------------------------------------------------------------------
26
+
27
+ def print_error(message: str) -> None:
28
+ err_console.print(f"[bold red]x[/bold red] {message}")
29
+
30
+
31
+ def print_warning(message: str) -> None:
32
+ console.print(f"[bold yellow]![/bold yellow] {message}")
33
+
34
+
35
+ def print_success(message: str) -> None:
36
+ console.print(f"[bold green]v[/bold green] {message}")
37
+
38
+
39
+ def print_info(message: str) -> None:
40
+ console.print(f"[bold blue]>[/bold blue] {message}")
41
+
42
+
43
+ def print_verbose(message: str) -> None:
44
+ console.print(f"[dim]{message}[/dim]")
45
+
46
+
47
+ # ---------------------------------------------------------------------------
48
+ # Diff 预览
49
+ # ---------------------------------------------------------------------------
50
+
51
+ def _status_color(status: str) -> str:
52
+ colors = {"A": "green", "M": "yellow", "D": "red", "R": "cyan"}
53
+ return colors.get(status, "white")
54
+
55
+
56
+ def _status_label(status: str) -> str:
57
+ labels = {"A": "新增", "M": "修改", "D": "删除", "R": "重命名"}
58
+ return labels.get(status, status)
59
+
60
+
61
+ def show_diff_summary(diff_result: DiffResult) -> None:
62
+ """展示变更摘要(文件树形式)。"""
63
+ total_ins = sum(f.insertions for f in diff_result.files)
64
+ total_del = sum(f.deletions for f in diff_result.files)
65
+
66
+ console.print()
67
+ print_info(f"分析暂存区变更...")
68
+ console.print()
69
+
70
+ header = f" 修改了 {len(diff_result.files)} 个文件 ([green]+{total_ins}[/green], [red]-{total_del}[/red])"
71
+ console.print(header)
72
+
73
+ for i, f in enumerate(diff_result.files):
74
+ color = _status_color(f.status)
75
+ is_last = i == len(diff_result.files) - 1
76
+ prefix = " └── " if is_last else " ├── "
77
+ console.print(f"{prefix}[{color}]{f.path}[/{color}] ([green]+{f.insertions}[/green], [red]-{f.deletions}[/red])")
78
+
79
+ console.print()
80
+
81
+
82
+ # ---------------------------------------------------------------------------
83
+ # Commit Message 展示
84
+ # ---------------------------------------------------------------------------
85
+
86
+ def show_commit_message(message: str) -> None:
87
+ """以面板形式展示 commit message。"""
88
+ panel = Panel(
89
+ Text(message),
90
+ title="[bold]Commit Message[/bold]",
91
+ border_style="cyan",
92
+ padding=(1, 2),
93
+ )
94
+ console.print(panel)
95
+
96
+
97
+ # ---------------------------------------------------------------------------
98
+ # 交互菜单
99
+ # ---------------------------------------------------------------------------
100
+
101
+ def prompt_action() -> str:
102
+ """展示操作菜单并获取用户选择。
103
+
104
+ Returns:
105
+ 用户选择: 'y' | 'e' | 'r' | 'q'
106
+ """
107
+ console.print(
108
+ "[bold][green]确认提交(y)[/green] "
109
+ "[yellow]编辑(e)[/yellow] "
110
+ "[blue]反馈重新生成(r)[/blue] "
111
+ "[red]放弃(q)[/red][/bold]"
112
+ )
113
+
114
+ while True:
115
+ choice = click.prompt("", prompt_suffix="> ", type=str).strip().lower()
116
+ if choice in ("y", "e", "r", "q"):
117
+ return choice
118
+ console.print("[dim]请输入 y/e/r/q[/dim]")
119
+
120
+
121
+ def prompt_feedback() -> str:
122
+ """获取用户的反馈意见。"""
123
+ console.print("[bold blue]>[/bold blue] 请输入你的反馈(告诉AI如何改进):")
124
+ return click.prompt("", prompt_suffix="> ", type=str).strip()
125
+
126
+
127
+ def prompt_edit(message: str) -> str:
128
+ """让用户编辑 commit message。使用 click.edit 打开编辑器。"""
129
+ edited = click.edit(message)
130
+ if edited is not None:
131
+ return edited.strip()
132
+ return message
133
+
134
+
135
+ def prompt_confirm(message: str) -> bool:
136
+ """简单的确认提示。"""
137
+ return click.confirm(message, default=True)
138
+
139
+
140
+ # ---------------------------------------------------------------------------
141
+ # 智能拆分展示
142
+ # ---------------------------------------------------------------------------
143
+
144
+ def show_split_suggestion(groups: list[CommitGroup]) -> None:
145
+ """展示拆分提交建议。"""
146
+ console.print()
147
+ print_info(f"建议拆分为 {len(groups)} 个原子提交:")
148
+ console.print()
149
+
150
+ for i, group in enumerate(groups, 1):
151
+ console.print(f" [bold cyan]提交 {i}[/bold cyan]: {group.message}")
152
+ for f in group.files:
153
+ console.print(f" - {f}")
154
+ console.print()
155
+
156
+
157
+ # ---------------------------------------------------------------------------
158
+ # Spinner 上下文管理
159
+ # ---------------------------------------------------------------------------
160
+
161
+ def spinner(message: str = "生成 commit message..."):
162
+ """返回 rich 的 spinner 上下文管理器。"""
163
+ return console.status(f"[bold blue]>[/bold blue] {message}", spinner="dots")
164
+
165
+
166
+ # ---------------------------------------------------------------------------
167
+ # 大提交警告
168
+ # ---------------------------------------------------------------------------
169
+
170
+ def warn_large_commit(file_count: int) -> bool:
171
+ """对大提交发出警告,询问是否继续。返回 True 表示继续。"""
172
+ print_warning(
173
+ f"暂存区包含 {file_count} 个文件,变更较多,建议拆分提交以保持每次提交的原子性。"
174
+ )
175
+ return prompt_confirm("是否继续?")
176
+
177
+
178
+ # ---------------------------------------------------------------------------
179
+ # 流式输出
180
+ # ---------------------------------------------------------------------------
181
+
182
+ @dataclass(slots=True)
183
+ class _Done:
184
+ """后台线程完成哨兵,携带 generator 的 return 值。"""
185
+ value: str
186
+
187
+
188
+ @dataclass(slots=True)
189
+ class _Error:
190
+ """后台线程异常哨兵,携带原始异常。"""
191
+ exc: BaseException
192
+
193
+
194
+ def _consume_stream(
195
+ chunks: Generator[str, None, str],
196
+ q: queue.Queue,
197
+ ) -> None:
198
+ """在后台线程中消费 generator,将 chunk 放入队列。"""
199
+ try:
200
+ while True:
201
+ chunk = next(chunks)
202
+ q.put(chunk)
203
+ except StopIteration as e:
204
+ q.put(_Done(value=e.value or ""))
205
+ except Exception as e:
206
+ q.put(_Error(exc=e))
207
+
208
+
209
+ def stream_commit_message(chunks: Generator[str, None, str]) -> str:
210
+ """流式展示 LLM 生成的 commit message,后台线程收集数据,主线程平滑渲染。
211
+
212
+ 通过将网络 I/O(generator 消费)放到后台线程,主线程专注于以固定节奏
213
+ 刷新 UI,避免因等待 LLM 响应而导致的画面冻结。
214
+
215
+ Args:
216
+ chunks: 生成器,逐块 yield 文本片段,最终 return 清理后的完整 message。
217
+
218
+ Returns:
219
+ 最终清理后的 commit message。
220
+ """
221
+ chunk_queue: queue.Queue = queue.Queue()
222
+ thread = Thread(target=_consume_stream, args=(chunks, chunk_queue), daemon=True)
223
+ thread.start()
224
+
225
+ parts: list[str] = []
226
+ final_message = ""
227
+ error: BaseException | None = None
228
+ done = False
229
+
230
+ with Live(
231
+ _make_stream_panel(""),
232
+ console=console,
233
+ refresh_per_second=30,
234
+ transient=True,
235
+ ) as live:
236
+ while not done:
237
+ got_new = False
238
+ # 批量 drain:非阻塞取出所有已到达的 chunk
239
+ while True:
240
+ try:
241
+ item: Union[str, _Done, _Error] = chunk_queue.get_nowait()
242
+ except queue.Empty:
243
+ break
244
+ if isinstance(item, _Done):
245
+ final_message = item.value
246
+ done = True
247
+ break
248
+ elif isinstance(item, _Error):
249
+ error = item.exc
250
+ done = True
251
+ break
252
+ else:
253
+ parts.append(item)
254
+ got_new = True
255
+
256
+ if got_new:
257
+ live.update(_make_stream_panel("".join(parts)))
258
+
259
+ if not done:
260
+ time.sleep(1 / 60)
261
+
262
+ thread.join(timeout=5)
263
+
264
+ if error is not None:
265
+ raise error
266
+
267
+ return final_message if final_message else "".join(parts).strip()
268
+
269
+
270
+ def _make_stream_panel(text: str) -> Panel:
271
+ """构建流式输出用的面板。"""
272
+ display = text if text else " "
273
+ return Panel(
274
+ Text(display),
275
+ title="[bold]Commit Message[/bold]",
276
+ subtitle="[dim]生成中...[/dim]" if text else None,
277
+ border_style="cyan",
278
+ padding=(1, 2),
279
+ )
@@ -0,0 +1,369 @@
1
+ Metadata-Version: 2.4
2
+ Name: acm-cli
3
+ Version: 0.1.0
4
+ Summary: 基于 LLM 的 Git Commit Message 自动生成工具
5
+ Project-URL: Homepage, https://github.com/hz-lxt/auto_commit_cli
6
+ Project-URL: Repository, https://github.com/hz-lxt/auto_commit_cli
7
+ Project-URL: Issues, https://github.com/hz-lxt/auto_commit_cli/issues
8
+ Author-email: huangzhao <572478035@qq.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai,automation,commit,commit-message,git,llm
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Version Control :: Git
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: click>=8.0
24
+ Requires-Dist: openai>=1.0
25
+ Requires-Dist: rich>=13.0
26
+ Requires-Dist: tomli-w>=1.0
27
+ Requires-Dist: tomli>=2.0; python_version < '3.11'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # ACM-CLI
31
+
32
+ 基于 LLM 的 Git Commit Message 自动生成工具。分析暂存区代码变更,自动生成符合规范的中文 commit message。
33
+
34
+ ## 功能特性
35
+
36
+ - 自动分析 `git diff --staged` 内容,调用 LLM 生成规范的 commit message
37
+ - 遵循 `type(scope): 描述` 格式,scope 根据文件目录自动推断,描述默认中文
38
+ - 支持确认提交、编辑、根据反馈多次重新生成、放弃等交互操作
39
+ - 智能 diff 截断:大变更自动截断并附加摘要,避免超出 token 限制
40
+ - 智能拆分提交:将一次大变更拆分为多个原子提交
41
+ - 多提供商支持:内置通义千问,兼容所有 OpenAI 接口的提供商
42
+ - 彩色终端界面(基于 rich)
43
+ - 流式输出:LLM 生成过程实时逐字显示,无需等待完整响应
44
+ - 全局配置 + 项目级配置,TOML 格式
45
+ - 反馈学习:自动记录用户反馈,动态优化后续生成的 prompt
46
+ - 自动暂存:暂存区为空时提示自动执行 `git add`
47
+
48
+ ## 环境要求
49
+
50
+ - Python >= 3.10
51
+ - Git
52
+
53
+ ## 安装
54
+
55
+ ```bash
56
+ # 使用 pip
57
+ pip install acm-cli
58
+
59
+ # 使用 uv
60
+ uv pip install acm-cli
61
+
62
+ # 从源码安装(开发模式)
63
+ git clone <repo-url> && cd auto_commit
64
+ uv venv --python 3.10 && source .venv/bin/activate
65
+ uv pip install -e .
66
+ ```
67
+
68
+ 安装完成后,终端即可使用 `acm` 命令。
69
+
70
+ ## 快速开始
71
+
72
+ ### 1. 初始化配置
73
+
74
+ 首次使用需要配置 LLM 提供商和 API Key:
75
+
76
+ ```bash
77
+ acm init
78
+ ```
79
+
80
+ 按提示依次完成:
81
+
82
+ ```
83
+ ACM 配置初始化
84
+
85
+ 可选提供商:
86
+ 1. qwen
87
+ 2. other
88
+ 选择提供商: 1
89
+ 输入 API Key: ****
90
+ 输入模型名称 (必填): qwen-plus
91
+ 自定义 Base URL (留空使用默认):
92
+ 输出语言 (zh-CN, en) [zh-CN]: zh-CN
93
+
94
+ v 配置已保存到: .acm.toml
95
+ ```
96
+
97
+ 生成全局配置(所有项目共用):
98
+
99
+ ```bash
100
+ acm init --global
101
+ ```
102
+
103
+ ### 2. 日常使用
104
+
105
+ ```bash
106
+ # 先暂存要提交的文件
107
+ git add .
108
+
109
+ # 自动生成 commit message
110
+ acm
111
+ ```
112
+
113
+ 工具会展示变更摘要,然后**实时流式显示**生成的 message,最后等待你选择操作:
114
+
115
+ ```
116
+ > 分析暂存区变更...
117
+
118
+ 修改了 3 个文件 (+45, -12)
119
+ ├── src/auth/login.py (+30, -5)
120
+ ├── src/auth/models.py (+10, -2)
121
+ └── tests/test_login.py (+5, -5)
122
+
123
+ > 生成 commit message...
124
+
125
+ ╭─────── Commit Message ───────╮
126
+ │ │
127
+ │ feat(auth): 实现用户登录认证功能 │
128
+ │ │
129
+ │ - 新增基于JWT的登录接口 │
130
+ │ - 添加用户模型字段校验 │
131
+ │ - 更新登录相关单元测试 │
132
+ │ │
133
+ ╰──────────────────────────────╯
134
+
135
+ [y] 确认提交 [e] 编辑 [r] 反馈重新生成 [q] 放弃
136
+ >
137
+ ```
138
+
139
+ | 操作 | 说明 |
140
+ |------|------|
141
+ | `y` | 确认,执行 `git commit` |
142
+ | `e` | 打开编辑器修改 message 后提交 |
143
+ | `r` | 输入反馈,LLM 根据反馈重新生成(可多次) |
144
+ | `q` | 放弃,不提交 |
145
+
146
+ ### 3. 反馈重新生成
147
+
148
+ 输入 `r` 后可以告诉 AI 如何改进:
149
+
150
+ ```
151
+ > r
152
+ > 请输入你的反馈(告诉AI如何改进):
153
+ > type应该是refactor不是feat
154
+
155
+ > 根据反馈重新生成...
156
+
157
+ ╭─────── Commit Message ───────╮
158
+ │ refactor(auth): 重构用户登录认证逻辑 │
159
+ ╰──────────────────────────────╯
160
+ ```
161
+
162
+ 反馈可以多次进行,直到满意为止。
163
+
164
+ ### 4. 自动暂存
165
+
166
+ 当暂存区为空但工作区存在未暂存的修改或未跟踪文件时,acm 会提示你是否自动执行 `git add -A`:
167
+
168
+ ```
169
+ ! 暂存区为空,但检测到未暂存的修改
170
+ 是否执行 git add . 将所有变更添加到暂存区并继续? [Y/n]: y
171
+ v 已执行 git add -A,所有变更已添加到暂存区
172
+
173
+ > 分析暂存区变更...
174
+ ```
175
+
176
+ 选择 `y` 后工具会自动暂存所有变更并继续生成 commit message,无需手动执行 `git add`。
177
+
178
+ ### 5. 同类变更收敛
179
+
180
+ 当多个文件的变更属于同一类操作时,生成的 commit message 会自动合并 scope,避免冗余:
181
+
182
+ ```
183
+ # 多个文件都是优化导入 -> 合并为一条
184
+ refactor(cve_service, cve_serializer): 优化导入和移除未使用模块
185
+
186
+ # 多个文件都是格式调整 -> 合并为一条
187
+ style(auth, api, utils): 统一代码格式化
188
+ ```
189
+
190
+ ### 6. 反馈学习
191
+
192
+ acm 会自动记录你的偏好到本地(`~/.acm/feedback.json`),包括:
193
+
194
+ - 使用反馈重新生成(`r`)时:记录原始 message、反馈内容、改进后 message
195
+ - 手动编辑(`e`)时:记录编辑前后的 message 差异
196
+
197
+ 后续生成时,acm 会**智能匹配**与当前 diff 最相关的历史反馈(按 scope/关键词匹配,最多注入 5 条),注入 prompt 让 LLM 学习你的偏好。最多保留最近 20 条记录。
198
+
199
+ ```
200
+ # 第一次使用:LLM 生成了 feat(auth): 添加登录功能
201
+ # 你反馈:type 应该是 fix 不是 feat
202
+ # LLM 改进为:fix(auth): 修复登录功能
203
+
204
+ # 之后修改 auth 相关代码时,LLM 会自动参考这条反馈
205
+ ```
206
+
207
+ 管理反馈记录:
208
+
209
+ ```bash
210
+ acm feedback list # 查看所有历史反馈
211
+ acm feedback clear # 清空所有反馈记录
212
+ ```
213
+
214
+ ## 命令参考
215
+
216
+ ### `acm` — 生成 commit message(默认命令)
217
+
218
+ ```bash
219
+ acm # 生成并交互式提交
220
+ acm --dry-run # 仅生成,不执行 git commit
221
+ acm --verbose # 输出调试信息(配置、prompt、LLM 响应等)
222
+ acm --split # 智能拆分为多个原子提交
223
+ acm --version # 查看版本
224
+ ```
225
+
226
+ ### `acm init` — 交互式初始化配置
227
+
228
+ ```bash
229
+ acm init # 生成项目级配置 .acm.toml
230
+ acm init --global # 生成全局配置 ~/.acm/config.toml
231
+ ```
232
+
233
+ ### `acm config` — 配置管理
234
+
235
+ ```bash
236
+ acm config list # 列出当前生效的所有配置
237
+ acm config get llm.model # 查看某个配置项
238
+ acm config set llm.model qwen-turbo # 修改项目级配置
239
+ acm config set llm.model qwen-turbo --global # 修改全局配置
240
+ ```
241
+
242
+ ### `acm feedback` — 反馈记录管理
243
+
244
+ ```bash
245
+ acm feedback list # 列出所有历史反馈记录
246
+ acm feedback clear # 清空所有反馈记录
247
+ ```
248
+
249
+ ## 配置文件
250
+
251
+ ### 配置文件位置
252
+
253
+ | 优先级 | 路径 | 说明 |
254
+ |--------|------|------|
255
+ | 高 | 项目根目录 `.acm.toml` | 项目级配置,仅当前项目生效 |
256
+ | 低 | `~/.acm/config.toml` | 全局配置,所有项目生效 |
257
+
258
+ 项目级配置会覆盖全局配置中的同名字段。
259
+
260
+ ### 配置文件示例
261
+
262
+ ```toml
263
+ [llm]
264
+ provider = "qwen" # 提供商名称
265
+ api_key = "sk-xxx" # API Key(建议改用环境变量)
266
+ model = "qwen-plus" # 模型名称(必填)
267
+ base_url = "" # 自定义 API 地址(留空使用提供商默认值)
268
+
269
+ [commit]
270
+ language = "zh-CN" # 描述语言,默认中文
271
+ max_diff_lines = 500 # diff 截断阈值(行数)
272
+ types = ["build", "ci"] # 自定义类型(追加到内置标准类型之上)
273
+
274
+ [prompt]
275
+ system = "" # 自定义 system prompt(留空使用内置默认)
276
+ extra = "" # 追加到默认 prompt 之后的额外指令
277
+ ```
278
+
279
+ ### API Key 管理
280
+
281
+ API Key 按以下优先级读取(高到低):
282
+
283
+ 1. 环境变量 `ACM_API_KEY`
284
+ 2. 提供商专用环境变量(如通义千问的 `DASHSCOPE_API_KEY`)
285
+ 3. 配置文件中的 `llm.api_key`
286
+
287
+ 推荐使用环境变量,避免将密钥写入配置文件:
288
+
289
+ ```bash
290
+ export ACM_API_KEY="sk-your-key-here"
291
+ # 或通义千问专用
292
+ export DASHSCOPE_API_KEY="sk-your-key-here"
293
+ ```
294
+
295
+ ## Commit Message 规范
296
+
297
+ 生成的 message 格式为 `type(scope): 中文描述`。
298
+
299
+ ### 内置 type 类型
300
+
301
+ | Type | 说明 |
302
+ |------|------|
303
+ | `feat` | 新功能 |
304
+ | `fix` | 缺陷修复 |
305
+ | `docs` | 文档变更 |
306
+ | `style` | 代码风格(不影响逻辑) |
307
+ | `refactor` | 重构 |
308
+ | `perf` | 性能优化 |
309
+ | `test` | 测试相关 |
310
+ | `chore` | 构建/工具变更 |
311
+
312
+ 可通过 `commit.types` 配置项追加自定义类型。
313
+
314
+ ### Scope 自动推断
315
+
316
+ 根据变更文件所在目录自动推断。例如修改了 `src/auth/login.py`,scope 为 `auth`。
317
+
318
+ 多模块变更时会用逗号分隔并分行描述:
319
+
320
+ ```
321
+ feat(auth,api): 添加用户认证模块
322
+
323
+ - auth: 实现基于JWT的登录认证逻辑
324
+ - api: 新增 /login 和 /logout 接口
325
+ ```
326
+
327
+ ## 提供商配置
328
+
329
+ ### 通义千问(内置)
330
+
331
+ ```toml
332
+ [llm]
333
+ provider = "qwen"
334
+ model = "qwen-plus" # 或 qwen-turbo, qwen-max 等
335
+ ```
336
+
337
+ ### 其他 OpenAI 兼容提供商
338
+
339
+ 任何兼容 OpenAI Chat API 的服务都可以使用,只需配置 `base_url`:
340
+
341
+ ```toml
342
+ # DeepSeek
343
+ [llm]
344
+ provider = "deepseek"
345
+ model = "deepseek-chat"
346
+ base_url = "https://api.deepseek.com/v1"
347
+
348
+ # Ollama 本地模型
349
+ [llm]
350
+ provider = "ollama"
351
+ model = "qwen2.5:7b"
352
+ base_url = "http://localhost:11434/v1"
353
+
354
+ # 智谱 AI
355
+ [llm]
356
+ provider = "zhipu"
357
+ model = "glm-4-flash"
358
+ base_url = "https://open.bigmodel.cn/api/paas/v4"
359
+ ```
360
+
361
+ ## 运行测试
362
+
363
+ ```bash
364
+ python -m unittest discover -s tests -v
365
+ ```
366
+
367
+ ## License
368
+
369
+ MIT
@@ -0,0 +1,18 @@
1
+ acm/__init__.py,sha256=o2xtxQu69ewo2c8lCYSwrVOdlp5_IE4-Jt4NpT48r5Q,91
2
+ acm/cli.py,sha256=-ZuZ_vQj-054TKtz_KfpOUsKSzNdFbi8IPRUIXs9jWo,14578
3
+ acm/config.py,sha256=_KSyCCVSYYHDZpO6ZM8XejNVz-c67WDoVBl1cJmWCB4,8368
4
+ acm/feedback.py,sha256=5whdUPyfX52TmoWHQgmKhoGbhtDVaUgEMUO2n4q3zc8,4542
5
+ acm/generator.py,sha256=rcBuqY1P4R4BHE7xhV1wj31YQPEbPh64LVPLlHDB-MU,4561
6
+ acm/git.py,sha256=aGSf1alIKGLC59QJsMq3j3ULUe5NvvYaJrkm0wUXwtM,6224
7
+ acm/prompt.py,sha256=dOoOu8dhjdwuauTASeE1nH-kcvErXo33nDXVDfO39ME,6223
8
+ acm/splitter.py,sha256=u3mWD529N47brzs-zrPEHvGCWxKHHOQLZ3kM9QeMTjc,2718
9
+ acm/ui.py,sha256=pvlCP4qmpO1wS3q7tZYE37ULcUAG8tkzNcRKiCnMb8Y,8787
10
+ acm/llm/__init__.py,sha256=_RCkUDHE8OdW1GDQzc1hn3G0XG51MSJNYHQasR5Ay04,841
11
+ acm/llm/base.py,sha256=3Lby6OimlWdQF53L5AtX4Ky6DiSQiytb075_SZj7jTc,1647
12
+ acm/llm/openai_compat.py,sha256=78QWbJFNGyp9waTC84VR5FBRf3TaLHYYo1AfFEsgO88,2540
13
+ acm/llm/qwen.py,sha256=ARAC_Eu7l6zu-OhmZCTVi0GPEgbrmr0vt77J450OLKY,540
14
+ acm_cli-0.1.0.dist-info/METADATA,sha256=FnT5vLAw54cTOlPE2CRiiN_Xdh2BdQcWZixA5jP1hwg,10246
15
+ acm_cli-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
16
+ acm_cli-0.1.0.dist-info/entry_points.txt,sha256=MSdN3GKf5V7mnZExG70tTcMhw8gT62TDL87xnz3j1S4,37
17
+ acm_cli-0.1.0.dist-info/licenses/LICENSE,sha256=R3-HWc6iPbskO4okGD3xiYoyWn8zkJo3qKEA9nP7ye4,1066
18
+ acm_cli-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ acm = acm.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 huangzhao
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.