auto-coder 0.1.398__py3-none-any.whl → 0.1.400__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 auto-coder might be problematic. Click here for more details.
- auto_coder-0.1.400.dist-info/METADATA +396 -0
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info}/RECORD +82 -29
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info}/WHEEL +1 -1
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info}/entry_points.txt +2 -0
- autocoder/agent/base_agentic/base_agent.py +2 -2
- autocoder/agent/base_agentic/tools/replace_in_file_tool_resolver.py +1 -1
- autocoder/agent/entry_command_agent/__init__.py +29 -0
- autocoder/agent/entry_command_agent/auto_tool.py +61 -0
- autocoder/agent/entry_command_agent/chat.py +475 -0
- autocoder/agent/entry_command_agent/designer.py +53 -0
- autocoder/agent/entry_command_agent/generate_command.py +50 -0
- autocoder/agent/entry_command_agent/project_reader.py +58 -0
- autocoder/agent/entry_command_agent/voice2text.py +71 -0
- autocoder/auto_coder.py +23 -548
- autocoder/auto_coder_runner.py +511 -8
- autocoder/chat/rules_command.py +1 -1
- autocoder/chat_auto_coder.py +6 -1
- autocoder/common/ac_style_command_parser/__init__.py +15 -0
- autocoder/common/ac_style_command_parser/example.py +7 -0
- autocoder/{command_parser.py → common/ac_style_command_parser/parser.py} +28 -45
- autocoder/common/ac_style_command_parser/test_parser.py +516 -0
- autocoder/common/auto_coder_lang.py +78 -0
- autocoder/common/command_completer_v2.py +1 -1
- autocoder/common/command_file_manager/examples.py +22 -8
- autocoder/common/command_file_manager/manager.py +37 -6
- autocoder/common/conversations/get_conversation_manager.py +143 -0
- autocoder/common/conversations/manager.py +122 -11
- autocoder/common/conversations/storage/index_manager.py +89 -0
- autocoder/common/pull_requests/__init__.py +256 -0
- autocoder/common/pull_requests/base_provider.py +191 -0
- autocoder/common/pull_requests/config.py +66 -0
- autocoder/common/pull_requests/example.py +1 -0
- autocoder/common/pull_requests/exceptions.py +46 -0
- autocoder/common/pull_requests/manager.py +201 -0
- autocoder/common/pull_requests/models.py +164 -0
- autocoder/common/pull_requests/providers/__init__.py +23 -0
- autocoder/common/pull_requests/providers/gitcode_provider.py +19 -0
- autocoder/common/pull_requests/providers/gitee_provider.py +20 -0
- autocoder/common/pull_requests/providers/github_provider.py +214 -0
- autocoder/common/pull_requests/providers/gitlab_provider.py +29 -0
- autocoder/common/pull_requests/test_module.py +1 -0
- autocoder/common/pull_requests/utils.py +344 -0
- autocoder/common/tokens/__init__.py +62 -0
- autocoder/common/tokens/counter.py +211 -0
- autocoder/common/tokens/file_detector.py +105 -0
- autocoder/common/tokens/filters.py +111 -0
- autocoder/common/tokens/models.py +28 -0
- autocoder/common/v2/agent/agentic_edit.py +312 -85
- autocoder/common/v2/agent/agentic_edit_types.py +11 -0
- autocoder/common/v2/code_auto_generate_editblock.py +10 -2
- autocoder/dispacher/__init__.py +10 -0
- autocoder/rags.py +0 -27
- autocoder/run_context.py +1 -0
- autocoder/sdk/__init__.py +188 -0
- autocoder/sdk/cli/__init__.py +15 -0
- autocoder/sdk/cli/__main__.py +26 -0
- autocoder/sdk/cli/completion_wrapper.py +38 -0
- autocoder/sdk/cli/formatters.py +211 -0
- autocoder/sdk/cli/handlers.py +175 -0
- autocoder/sdk/cli/install_completion.py +301 -0
- autocoder/sdk/cli/main.py +286 -0
- autocoder/sdk/cli/options.py +73 -0
- autocoder/sdk/constants.py +102 -0
- autocoder/sdk/core/__init__.py +20 -0
- autocoder/sdk/core/auto_coder_core.py +880 -0
- autocoder/sdk/core/bridge.py +500 -0
- autocoder/sdk/example.py +0 -0
- autocoder/sdk/exceptions.py +72 -0
- autocoder/sdk/models/__init__.py +19 -0
- autocoder/sdk/models/messages.py +209 -0
- autocoder/sdk/models/options.py +196 -0
- autocoder/sdk/models/responses.py +311 -0
- autocoder/sdk/session/__init__.py +32 -0
- autocoder/sdk/session/session.py +106 -0
- autocoder/sdk/session/session_manager.py +56 -0
- autocoder/sdk/utils/__init__.py +24 -0
- autocoder/sdk/utils/formatters.py +216 -0
- autocoder/sdk/utils/io_utils.py +302 -0
- autocoder/sdk/utils/validators.py +287 -0
- autocoder/version.py +2 -1
- auto_coder-0.1.398.dist-info/METADATA +0 -111
- autocoder/common/conversations/compatibility.py +0 -303
- autocoder/common/conversations/conversation_manager.py +0 -502
- autocoder/common/conversations/example.py +0 -152
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info/licenses}/LICENSE +0 -0
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
|
|
2
|
+
#!/usr/bin/env python3
|
|
3
|
+
"""
|
|
4
|
+
Auto-Coder CLI 自动补全安装脚本
|
|
5
|
+
|
|
6
|
+
该脚本帮助用户在不同的 shell 环境中安装 auto-coder.run 命令的自动补全功能。
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
import subprocess
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CompletionInstaller:
|
|
17
|
+
"""自动补全安装器"""
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
self.shell = self._detect_shell()
|
|
21
|
+
self.home_dir = Path.home()
|
|
22
|
+
|
|
23
|
+
def _detect_shell(self) -> str:
|
|
24
|
+
"""检测当前使用的 shell"""
|
|
25
|
+
shell = os.environ.get('SHELL', '')
|
|
26
|
+
if 'bash' in shell:
|
|
27
|
+
return 'bash'
|
|
28
|
+
elif 'zsh' in shell:
|
|
29
|
+
return 'zsh'
|
|
30
|
+
elif 'fish' in shell:
|
|
31
|
+
return 'fish'
|
|
32
|
+
else:
|
|
33
|
+
return 'unknown'
|
|
34
|
+
|
|
35
|
+
def _get_completion_script(self, shell: str) -> str:
|
|
36
|
+
"""获取对应 shell 的补全脚本"""
|
|
37
|
+
# 获取当前 Python 环境的路径
|
|
38
|
+
python_path = sys.executable
|
|
39
|
+
register_cmd_path = os.path.join(os.path.dirname(python_path), 'register-python-argcomplete')
|
|
40
|
+
|
|
41
|
+
# 检查 register-python-argcomplete 是否存在
|
|
42
|
+
if not os.path.exists(register_cmd_path):
|
|
43
|
+
# 如果不存在,提供一个简化的解决方案
|
|
44
|
+
return self._get_simple_completion_script(shell)
|
|
45
|
+
|
|
46
|
+
if shell == 'bash':
|
|
47
|
+
return f'''# Auto-Coder CLI 自动补全
|
|
48
|
+
eval "$({register_cmd_path} auto-coder.run 2>/dev/null || echo '')"'''
|
|
49
|
+
elif shell == 'zsh':
|
|
50
|
+
return f'''# Auto-Coder CLI 自动补全
|
|
51
|
+
# 检查是否在 zsh 环境中
|
|
52
|
+
if [[ -n "$ZSH_VERSION" ]]; then
|
|
53
|
+
autoload -U +X bashcompinit && bashcompinit 2>/dev/null
|
|
54
|
+
fi
|
|
55
|
+
eval "$({register_cmd_path} auto-coder.run 2>/dev/null || echo '')"'''
|
|
56
|
+
elif shell == 'fish':
|
|
57
|
+
return f'''# Auto-Coder CLI 自动补全
|
|
58
|
+
{register_cmd_path} --shell fish auto-coder.run 2>/dev/null | source'''
|
|
59
|
+
else:
|
|
60
|
+
return ''
|
|
61
|
+
|
|
62
|
+
def _get_simple_completion_script(self, shell: str) -> str:
|
|
63
|
+
"""获取简化的补全脚本(当 register-python-argcomplete 不可用时)"""
|
|
64
|
+
python_path = sys.executable
|
|
65
|
+
|
|
66
|
+
if shell in ['bash', 'zsh']:
|
|
67
|
+
return f'''# Auto-Coder CLI 自动补全(简化版本)
|
|
68
|
+
# 注意:需要安装 argcomplete 包才能使用完整功能
|
|
69
|
+
_auto_coder_run_completion() {{
|
|
70
|
+
local cur prev opts
|
|
71
|
+
COMPREPLY=()
|
|
72
|
+
cur="${{COMP_WORDS[COMP_CWORD]}}"
|
|
73
|
+
prev="${{COMP_WORDS[COMP_CWORD-1]}}"
|
|
74
|
+
|
|
75
|
+
opts="-h --help -p --print -c --continue -r --resume --output-format --input-format -v --verbose --max-turns --system-prompt --allowed-tools --permission-mode"
|
|
76
|
+
|
|
77
|
+
case "${{prev}}" in
|
|
78
|
+
--allowed-tools)
|
|
79
|
+
COMPREPLY=( $(compgen -W "execute_command read_file write_to_file replace_in_file search_files list_files list_code_definition_names ask_followup_question attempt_completion list_package_info mcp_tool rag_tool" -- ${{cur}}) )
|
|
80
|
+
return 0
|
|
81
|
+
;;
|
|
82
|
+
--output-format|--input-format)
|
|
83
|
+
COMPREPLY=( $(compgen -W "text json stream-json" -- ${{cur}}) )
|
|
84
|
+
return 0
|
|
85
|
+
;;
|
|
86
|
+
--permission-mode)
|
|
87
|
+
COMPREPLY=( $(compgen -W "manual acceptEdits" -- ${{cur}}) )
|
|
88
|
+
return 0
|
|
89
|
+
;;
|
|
90
|
+
esac
|
|
91
|
+
|
|
92
|
+
COMPREPLY=( $(compgen -W "${{opts}}" -- ${{cur}}) )
|
|
93
|
+
}}
|
|
94
|
+
complete -F _auto_coder_run_completion auto-coder.run'''
|
|
95
|
+
else:
|
|
96
|
+
return ''
|
|
97
|
+
|
|
98
|
+
def _get_config_file(self, shell: str) -> Optional[Path]:
|
|
99
|
+
"""获取对应 shell 的配置文件路径"""
|
|
100
|
+
if shell == 'bash':
|
|
101
|
+
# 按优先级检查 bash 配置文件
|
|
102
|
+
candidates = ['.bashrc', '.bash_profile', '.profile']
|
|
103
|
+
for candidate in candidates:
|
|
104
|
+
config_file = self.home_dir / candidate
|
|
105
|
+
if config_file.exists():
|
|
106
|
+
return config_file
|
|
107
|
+
# 如果都不存在,默认使用 .bashrc
|
|
108
|
+
return self.home_dir / '.bashrc'
|
|
109
|
+
elif shell == 'zsh':
|
|
110
|
+
return self.home_dir / '.zshrc'
|
|
111
|
+
elif shell == 'fish':
|
|
112
|
+
config_dir = self.home_dir / '.config' / 'fish'
|
|
113
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
114
|
+
return config_dir / 'config.fish'
|
|
115
|
+
else:
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
def check_argcomplete_installed(self) -> bool:
|
|
119
|
+
"""检查 argcomplete 是否已安装"""
|
|
120
|
+
try:
|
|
121
|
+
import argcomplete
|
|
122
|
+
return True
|
|
123
|
+
except ImportError:
|
|
124
|
+
return False
|
|
125
|
+
|
|
126
|
+
def check_register_command_available(self) -> bool:
|
|
127
|
+
"""检查 register-python-argcomplete 命令是否可用"""
|
|
128
|
+
try:
|
|
129
|
+
result = subprocess.run(['register-python-argcomplete', '--help'],
|
|
130
|
+
capture_output=True, text=True)
|
|
131
|
+
return result.returncode == 0
|
|
132
|
+
except FileNotFoundError:
|
|
133
|
+
return False
|
|
134
|
+
|
|
135
|
+
def install_completion(self, force: bool = False) -> bool:
|
|
136
|
+
"""安装自动补全功能"""
|
|
137
|
+
print(f"检测到的 shell: {self.shell}")
|
|
138
|
+
|
|
139
|
+
# 检查依赖
|
|
140
|
+
if not self.check_argcomplete_installed():
|
|
141
|
+
print("错误: argcomplete 包未安装")
|
|
142
|
+
print("请运行: pip install argcomplete")
|
|
143
|
+
return False
|
|
144
|
+
|
|
145
|
+
if not self.check_register_command_available():
|
|
146
|
+
print("错误: register-python-argcomplete 命令不可用")
|
|
147
|
+
print("请确保 argcomplete 正确安装并在 PATH 中")
|
|
148
|
+
return False
|
|
149
|
+
|
|
150
|
+
if self.shell == 'unknown':
|
|
151
|
+
print("错误: 无法检测到支持的 shell")
|
|
152
|
+
print("支持的 shell: bash, zsh, fish")
|
|
153
|
+
return False
|
|
154
|
+
|
|
155
|
+
config_file = self._get_config_file(self.shell)
|
|
156
|
+
if not config_file:
|
|
157
|
+
print(f"错误: 无法确定 {self.shell} 的配置文件")
|
|
158
|
+
return False
|
|
159
|
+
|
|
160
|
+
completion_script = self._get_completion_script(self.shell)
|
|
161
|
+
if not completion_script:
|
|
162
|
+
print(f"错误: 不支持的 shell: {self.shell}")
|
|
163
|
+
return False
|
|
164
|
+
|
|
165
|
+
# 检查是否已经安装
|
|
166
|
+
if config_file.exists():
|
|
167
|
+
content = config_file.read_text()
|
|
168
|
+
if 'auto-coder.run' in content and not force:
|
|
169
|
+
print(f"自动补全似乎已经安装在 {config_file}")
|
|
170
|
+
print("使用 --force 参数强制重新安装")
|
|
171
|
+
return True
|
|
172
|
+
|
|
173
|
+
# 添加补全脚本到配置文件
|
|
174
|
+
try:
|
|
175
|
+
with open(config_file, 'a') as f:
|
|
176
|
+
f.write(f'\n# Auto-Coder CLI 自动补全\n')
|
|
177
|
+
f.write(f'{completion_script}\n')
|
|
178
|
+
|
|
179
|
+
print(f"✓ 自动补全已安装到 {config_file}")
|
|
180
|
+
print(f"请重新加载 shell 配置或运行: source {config_file}")
|
|
181
|
+
return True
|
|
182
|
+
|
|
183
|
+
except Exception as e:
|
|
184
|
+
print(f"错误: 无法写入配置文件 {config_file}: {e}")
|
|
185
|
+
return False
|
|
186
|
+
|
|
187
|
+
def uninstall_completion(self) -> bool:
|
|
188
|
+
"""卸载自动补全功能"""
|
|
189
|
+
config_file = self._get_config_file(self.shell)
|
|
190
|
+
if not config_file or not config_file.exists():
|
|
191
|
+
print("未找到配置文件或自动补全未安装")
|
|
192
|
+
return True
|
|
193
|
+
|
|
194
|
+
try:
|
|
195
|
+
lines = config_file.read_text().splitlines()
|
|
196
|
+
new_lines = []
|
|
197
|
+
skip_next = False
|
|
198
|
+
|
|
199
|
+
for line in lines:
|
|
200
|
+
if '# Auto-Coder CLI 自动补全' in line:
|
|
201
|
+
skip_next = True
|
|
202
|
+
continue
|
|
203
|
+
elif skip_next and 'auto-coder.run' in line:
|
|
204
|
+
skip_next = False
|
|
205
|
+
continue
|
|
206
|
+
else:
|
|
207
|
+
skip_next = False
|
|
208
|
+
new_lines.append(line)
|
|
209
|
+
|
|
210
|
+
config_file.write_text('\n'.join(new_lines))
|
|
211
|
+
print(f"✓ 自动补全已从 {config_file} 中移除")
|
|
212
|
+
return True
|
|
213
|
+
|
|
214
|
+
except Exception as e:
|
|
215
|
+
print(f"错误: 无法修改配置文件 {config_file}: {e}")
|
|
216
|
+
return False
|
|
217
|
+
|
|
218
|
+
def test_completion(self) -> bool:
|
|
219
|
+
"""测试自动补全是否工作"""
|
|
220
|
+
print("测试自动补全功能...")
|
|
221
|
+
try:
|
|
222
|
+
# 尝试获取补全建议
|
|
223
|
+
result = subprocess.run([
|
|
224
|
+
'python', '-c',
|
|
225
|
+
'import argcomplete; from autocoder.sdk.cli.main import AutoCoderCLI; '
|
|
226
|
+
'parser = AutoCoderCLI.parse_args.__func__(AutoCoderCLI, []); '
|
|
227
|
+
'print("自动补全功能正常")'
|
|
228
|
+
], capture_output=True, text=True, timeout=5)
|
|
229
|
+
|
|
230
|
+
if result.returncode == 0:
|
|
231
|
+
print("✓ 自动补全功能测试通过")
|
|
232
|
+
return True
|
|
233
|
+
else:
|
|
234
|
+
print(f"✗ 自动补全功能测试失败: {result.stderr}")
|
|
235
|
+
return False
|
|
236
|
+
|
|
237
|
+
except Exception as e:
|
|
238
|
+
print(f"✗ 自动补全功能测试失败: {e}")
|
|
239
|
+
return False
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def main():
|
|
243
|
+
"""主函数"""
|
|
244
|
+
import argparse
|
|
245
|
+
|
|
246
|
+
parser = argparse.ArgumentParser(
|
|
247
|
+
description="Auto-Coder CLI 自动补全安装工具",
|
|
248
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
249
|
+
epilog="""
|
|
250
|
+
使用示例:
|
|
251
|
+
# 安装自动补全
|
|
252
|
+
python -m autocoder.sdk.cli.install_completion install
|
|
253
|
+
|
|
254
|
+
# 强制重新安装
|
|
255
|
+
python -m autocoder.sdk.cli.install_completion install --force
|
|
256
|
+
|
|
257
|
+
# 卸载自动补全
|
|
258
|
+
python -m autocoder.sdk.cli.install_completion uninstall
|
|
259
|
+
|
|
260
|
+
# 测试自动补全
|
|
261
|
+
python -m autocoder.sdk.cli.install_completion test
|
|
262
|
+
"""
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
subparsers = parser.add_subparsers(dest='command', help='可用命令')
|
|
266
|
+
|
|
267
|
+
# 安装命令
|
|
268
|
+
install_parser = subparsers.add_parser('install', help='安装自动补全')
|
|
269
|
+
install_parser.add_argument('--force', action='store_true', help='强制重新安装')
|
|
270
|
+
|
|
271
|
+
# 卸载命令
|
|
272
|
+
subparsers.add_parser('uninstall', help='卸载自动补全')
|
|
273
|
+
|
|
274
|
+
# 测试命令
|
|
275
|
+
subparsers.add_parser('test', help='测试自动补全功能')
|
|
276
|
+
|
|
277
|
+
args = parser.parse_args()
|
|
278
|
+
|
|
279
|
+
if not args.command:
|
|
280
|
+
parser.print_help()
|
|
281
|
+
return 1
|
|
282
|
+
|
|
283
|
+
installer = CompletionInstaller()
|
|
284
|
+
|
|
285
|
+
if args.command == 'install':
|
|
286
|
+
success = installer.install_completion(force=args.force)
|
|
287
|
+
return 0 if success else 1
|
|
288
|
+
elif args.command == 'uninstall':
|
|
289
|
+
success = installer.uninstall_completion()
|
|
290
|
+
return 0 if success else 1
|
|
291
|
+
elif args.command == 'test':
|
|
292
|
+
success = installer.test_completion()
|
|
293
|
+
return 0 if success else 1
|
|
294
|
+
else:
|
|
295
|
+
parser.print_help()
|
|
296
|
+
return 1
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
if __name__ == '__main__':
|
|
300
|
+
sys.exit(main())
|
|
301
|
+
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI 主入口点模块
|
|
3
|
+
|
|
4
|
+
提供命令行接口的主要实现,处理参数解析和命令执行。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import argparse
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Optional, List, Dict, Any, Union
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
import argcomplete
|
|
14
|
+
ARGCOMPLETE_AVAILABLE = True
|
|
15
|
+
except ImportError:
|
|
16
|
+
ARGCOMPLETE_AVAILABLE = False
|
|
17
|
+
|
|
18
|
+
from .options import CLIOptions, CLIResult
|
|
19
|
+
from .handlers import PrintModeHandler
|
|
20
|
+
from ..exceptions import AutoCoderSDKError
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AutoCoderCLI:
|
|
24
|
+
"""命令行接口主类,处理命令行参数和执行相应的操作。"""
|
|
25
|
+
|
|
26
|
+
def __init__(self):
|
|
27
|
+
"""初始化CLI实例。"""
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
def run(self, options: CLIOptions, cwd: Optional[str] = None) -> CLIResult:
|
|
31
|
+
"""
|
|
32
|
+
运行CLI命令 - 统一使用 Print Mode。
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
options: CLI选项
|
|
36
|
+
cwd: 当前工作目录,如果为None则使用系统当前目录
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
命令执行结果
|
|
40
|
+
"""
|
|
41
|
+
try:
|
|
42
|
+
# 验证选项
|
|
43
|
+
options.validate()
|
|
44
|
+
|
|
45
|
+
# 移除模式判断,直接使用 PrintModeHandler
|
|
46
|
+
return self.handle_print_mode(options, cwd)
|
|
47
|
+
|
|
48
|
+
except Exception as e:
|
|
49
|
+
return CLIResult(success=False, error=str(e))
|
|
50
|
+
|
|
51
|
+
def handle_print_mode(self, options: CLIOptions, cwd: Optional[str] = None) -> CLIResult:
|
|
52
|
+
"""
|
|
53
|
+
处理打印模式。
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
options: CLI选项
|
|
57
|
+
cwd: 当前工作目录
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
命令执行结果
|
|
61
|
+
"""
|
|
62
|
+
handler = PrintModeHandler(options, cwd)
|
|
63
|
+
return handler.handle()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def parse_args(cls, args: Optional[List[str]] = None) -> CLIOptions:
|
|
68
|
+
"""
|
|
69
|
+
解析命令行参数。
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
args: 命令行参数列表,如果为None则使用sys.argv
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
解析后的CLI选项
|
|
76
|
+
"""
|
|
77
|
+
parser = argparse.ArgumentParser(
|
|
78
|
+
description="Auto-Coder 命令行工具",
|
|
79
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
80
|
+
epilog="""
|
|
81
|
+
示例:
|
|
82
|
+
# 基本使用
|
|
83
|
+
auto-coder.run "Write a function to calculate Fibonacci numbers" --model gpt-4
|
|
84
|
+
|
|
85
|
+
# 通过管道提供输入
|
|
86
|
+
echo "Explain this code" | auto-coder.run --model gpt-4
|
|
87
|
+
|
|
88
|
+
# 指定输出格式
|
|
89
|
+
auto-coder.run "Generate a hello world function" --output-format json --model gpt-4
|
|
90
|
+
|
|
91
|
+
# 继续最近的对话
|
|
92
|
+
auto-coder.run --continue "继续修改代码" --model gpt-4
|
|
93
|
+
|
|
94
|
+
# 恢复特定会话
|
|
95
|
+
auto-coder.run --resume 550e8400-e29b-41d4-a716-446655440000 "新的请求" --model gpt-4
|
|
96
|
+
|
|
97
|
+
# 组合使用多个选项
|
|
98
|
+
auto-coder.run "Optimize this code" --model claude-3-sonnet --max-turns 5 --verbose
|
|
99
|
+
"""
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# 会话选项(移除模式选择,--continue 和 --resume 作为独立参数)
|
|
103
|
+
parser.add_argument("-c", "--continue", dest="continue_session", action="store_true",
|
|
104
|
+
help="继续最近的对话")
|
|
105
|
+
parser.add_argument("-r", "--resume", dest="resume_session", metavar="SESSION_ID",
|
|
106
|
+
help="恢复特定会话")
|
|
107
|
+
|
|
108
|
+
# 输入输出选项
|
|
109
|
+
parser.add_argument("prompt", nargs="?", help="提示内容,如果未提供则从stdin读取")
|
|
110
|
+
parser.add_argument("--output-format", choices=["text", "json", "stream-json"],
|
|
111
|
+
default="text", help="输出格式 (默认: text)")
|
|
112
|
+
parser.add_argument("--input-format", choices=["text", "json", "stream-json"],
|
|
113
|
+
default="text", help="输入格式 (默认: text)")
|
|
114
|
+
parser.add_argument("-v", "--verbose", action="store_true", help="输出详细信息")
|
|
115
|
+
|
|
116
|
+
# 高级选项
|
|
117
|
+
advanced = parser.add_argument_group("高级选项")
|
|
118
|
+
advanced.add_argument("--max-turns", type=int, default= -1, help="最大对话轮数 (默认: -1 不限制)")
|
|
119
|
+
advanced.add_argument("--system-prompt", help="系统提示")
|
|
120
|
+
advanced.add_argument("--allowed-tools", nargs="+", help="允许使用的工具列表")
|
|
121
|
+
advanced.add_argument("--permission-mode", choices=["manual", "acceptEdits"],
|
|
122
|
+
default="manual", help="权限模式 (默认: manual)")
|
|
123
|
+
advanced.add_argument("--model", required=True, help="指定使用的模型名称 (如: gpt-4, gpt-3.5-turbo, claude-3-sonnet 等)")
|
|
124
|
+
advanced.add_argument("--pr", action="store_true", help="创建 Pull Request")
|
|
125
|
+
|
|
126
|
+
# 启用自动补全
|
|
127
|
+
if ARGCOMPLETE_AVAILABLE:
|
|
128
|
+
# 添加自定义补全器
|
|
129
|
+
cls._setup_completers(parser)
|
|
130
|
+
argcomplete.autocomplete(parser)
|
|
131
|
+
|
|
132
|
+
# 解析参数
|
|
133
|
+
parsed_args = parser.parse_args(args)
|
|
134
|
+
|
|
135
|
+
# 转换为CLIOptions
|
|
136
|
+
options = CLIOptions(
|
|
137
|
+
continue_session=parsed_args.continue_session,
|
|
138
|
+
resume_session=parsed_args.resume_session,
|
|
139
|
+
prompt=parsed_args.prompt,
|
|
140
|
+
output_format=parsed_args.output_format,
|
|
141
|
+
input_format=parsed_args.input_format,
|
|
142
|
+
verbose=parsed_args.verbose,
|
|
143
|
+
max_turns=parsed_args.max_turns,
|
|
144
|
+
system_prompt=parsed_args.system_prompt,
|
|
145
|
+
allowed_tools=parsed_args.allowed_tools or [],
|
|
146
|
+
permission_mode=parsed_args.permission_mode,
|
|
147
|
+
model=parsed_args.model,
|
|
148
|
+
pr=parsed_args.pr
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
return options
|
|
152
|
+
|
|
153
|
+
@classmethod
|
|
154
|
+
def _setup_completers(cls, parser: argparse.ArgumentParser) -> None:
|
|
155
|
+
"""设置自定义补全器"""
|
|
156
|
+
if not ARGCOMPLETE_AVAILABLE:
|
|
157
|
+
return
|
|
158
|
+
|
|
159
|
+
# 为 --allowed-tools 参数设置补全器
|
|
160
|
+
def tools_completer(prefix, parsed_args, **kwargs):
|
|
161
|
+
"""工具名称补全器"""
|
|
162
|
+
available_tools = [
|
|
163
|
+
"execute_command",
|
|
164
|
+
"read_file",
|
|
165
|
+
"write_to_file",
|
|
166
|
+
"replace_in_file",
|
|
167
|
+
"search_files",
|
|
168
|
+
"list_files",
|
|
169
|
+
"list_code_definition_names",
|
|
170
|
+
"ask_followup_question",
|
|
171
|
+
"attempt_completion",
|
|
172
|
+
"list_package_info",
|
|
173
|
+
"mcp_tool",
|
|
174
|
+
"rag_tool"
|
|
175
|
+
]
|
|
176
|
+
return [tool for tool in available_tools if tool.startswith(prefix)]
|
|
177
|
+
|
|
178
|
+
# 为 --resume 参数设置会话ID补全器
|
|
179
|
+
def session_id_completer(prefix, parsed_args, **kwargs):
|
|
180
|
+
"""会话ID补全器"""
|
|
181
|
+
try:
|
|
182
|
+
# 这里可以从会话存储中获取可用的会话ID
|
|
183
|
+
# 目前返回示例会话ID格式
|
|
184
|
+
return [
|
|
185
|
+
"550e8400-e29b-41d4-a716-446655440000",
|
|
186
|
+
"6ba7b810-9dad-11d1-80b4-00c04fd430c8",
|
|
187
|
+
"6ba7b811-9dad-11d1-80b4-00c04fd430c8"
|
|
188
|
+
]
|
|
189
|
+
except Exception:
|
|
190
|
+
return []
|
|
191
|
+
|
|
192
|
+
# 为 prompt 参数设置示例补全器
|
|
193
|
+
def prompt_completer(prefix, parsed_args, **kwargs):
|
|
194
|
+
"""提示内容补全器"""
|
|
195
|
+
common_prompts = [
|
|
196
|
+
"Write a function to calculate Fibonacci numbers",
|
|
197
|
+
"Explain this code",
|
|
198
|
+
"Generate a hello world function",
|
|
199
|
+
"Create a simple web page",
|
|
200
|
+
"Write unit tests for this code",
|
|
201
|
+
"Refactor this function",
|
|
202
|
+
"Add error handling",
|
|
203
|
+
"Optimize this algorithm",
|
|
204
|
+
"Document this code",
|
|
205
|
+
"Fix the bug in this code"
|
|
206
|
+
]
|
|
207
|
+
return [prompt for prompt in common_prompts if prompt.lower().startswith(prefix.lower())]
|
|
208
|
+
|
|
209
|
+
# 为 --model 参数设置模型名称补全器
|
|
210
|
+
def model_completer(prefix, parsed_args, **kwargs):
|
|
211
|
+
"""模型名称补全器"""
|
|
212
|
+
common_models = [
|
|
213
|
+
# OpenAI models
|
|
214
|
+
"gpt-4",
|
|
215
|
+
"gpt-4-turbo",
|
|
216
|
+
"gpt-4-turbo-preview",
|
|
217
|
+
"gpt-4-0125-preview",
|
|
218
|
+
"gpt-4-1106-preview",
|
|
219
|
+
"gpt-3.5-turbo",
|
|
220
|
+
"gpt-3.5-turbo-16k",
|
|
221
|
+
"gpt-3.5-turbo-1106",
|
|
222
|
+
# Anthropic models
|
|
223
|
+
"claude-3-opus",
|
|
224
|
+
"claude-3-sonnet",
|
|
225
|
+
"claude-3-haiku",
|
|
226
|
+
"claude-2.1",
|
|
227
|
+
"claude-2.0",
|
|
228
|
+
"claude-instant-1.2",
|
|
229
|
+
# Google models
|
|
230
|
+
"gemini-pro",
|
|
231
|
+
"gemini-pro-vision",
|
|
232
|
+
# Local/Open source models
|
|
233
|
+
"llama2-7b",
|
|
234
|
+
"llama2-13b",
|
|
235
|
+
"llama2-70b",
|
|
236
|
+
"codellama-7b",
|
|
237
|
+
"codellama-13b",
|
|
238
|
+
"codellama-34b",
|
|
239
|
+
"mistral-7b",
|
|
240
|
+
"mixtral-8x7b",
|
|
241
|
+
# Azure OpenAI
|
|
242
|
+
"azure-gpt-4",
|
|
243
|
+
"azure-gpt-35-turbo",
|
|
244
|
+
]
|
|
245
|
+
return [model for model in common_models if model.lower().startswith(prefix.lower())]
|
|
246
|
+
|
|
247
|
+
# 应用补全器到对应的参数
|
|
248
|
+
for action in parser._actions:
|
|
249
|
+
if hasattr(action, 'dest'):
|
|
250
|
+
if action.dest == 'allowed_tools':
|
|
251
|
+
action.completer = tools_completer
|
|
252
|
+
elif action.dest == 'resume_session':
|
|
253
|
+
action.completer = session_id_completer
|
|
254
|
+
elif action.dest == 'prompt':
|
|
255
|
+
action.completer = prompt_completer
|
|
256
|
+
elif action.dest == 'model':
|
|
257
|
+
action.completer = model_completer
|
|
258
|
+
|
|
259
|
+
@classmethod
|
|
260
|
+
def main(cls) -> int:
|
|
261
|
+
"""
|
|
262
|
+
CLI主入口点。
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
退出码,0表示成功,非0表示失败
|
|
266
|
+
"""
|
|
267
|
+
try:
|
|
268
|
+
options = cls.parse_args()
|
|
269
|
+
cli = cls()
|
|
270
|
+
result = cli.run(options)
|
|
271
|
+
|
|
272
|
+
if result.success:
|
|
273
|
+
if result.output:
|
|
274
|
+
print(result.output)
|
|
275
|
+
return 0
|
|
276
|
+
else:
|
|
277
|
+
print(f"错误: {result.error}", file=sys.stderr)
|
|
278
|
+
return 1
|
|
279
|
+
|
|
280
|
+
except Exception as e:
|
|
281
|
+
print(f"未处理的错误: {str(e)}", file=sys.stderr)
|
|
282
|
+
return 1
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
if __name__ == "__main__":
|
|
286
|
+
sys.exit(AutoCoderCLI.main())
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI 选项定义模块
|
|
3
|
+
|
|
4
|
+
定义命令行接口的选项和结果数据结构。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from typing import Optional, Dict, Any
|
|
9
|
+
|
|
10
|
+
from ..constants import DEFAULT_MODEL
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class CLIOptions:
|
|
15
|
+
"""CLI选项数据类,用于配置命令行工具的行为。"""
|
|
16
|
+
|
|
17
|
+
# 会话选项
|
|
18
|
+
continue_session: bool = False # 继续最近的对话
|
|
19
|
+
resume_session: Optional[str] = None # 恢复特定会话的ID
|
|
20
|
+
|
|
21
|
+
# 输入选项
|
|
22
|
+
prompt: Optional[str] = None # 提示内容,如果为None则从stdin读取
|
|
23
|
+
input_format: str = "text" # 输入格式,可选值: text, json, stream-json
|
|
24
|
+
|
|
25
|
+
# 输出选项
|
|
26
|
+
output_format: str = "text" # 输出格式,可选值: text, json, stream-json
|
|
27
|
+
verbose: bool = False # 是否输出详细信息
|
|
28
|
+
|
|
29
|
+
# 高级选项
|
|
30
|
+
max_turns: int = 3 # 最大对话轮数
|
|
31
|
+
system_prompt: Optional[str] = None # 系统提示
|
|
32
|
+
allowed_tools: list = field(default_factory=list) # 允许使用的工具列表
|
|
33
|
+
permission_mode: str = "manual" # 权限模式,可选值: manual, acceptEdits
|
|
34
|
+
model: Optional[str] = None # 模型名称,如 gpt-4, gpt-3.5-turbo 等
|
|
35
|
+
pr: bool = False # 是否创建 PR
|
|
36
|
+
|
|
37
|
+
def validate(self) -> None:
|
|
38
|
+
"""验证选项的有效性。"""
|
|
39
|
+
# 验证输出格式
|
|
40
|
+
valid_formats = ["text", "json", "stream-json"]
|
|
41
|
+
if self.output_format not in valid_formats:
|
|
42
|
+
raise ValueError(f"无效的输出格式: {self.output_format},有效值为: {', '.join(valid_formats)}")
|
|
43
|
+
|
|
44
|
+
# 验证输入格式
|
|
45
|
+
if self.input_format not in valid_formats:
|
|
46
|
+
raise ValueError(f"无效的输入格式: {self.input_format},有效值为: {', '.join(valid_formats)}")
|
|
47
|
+
|
|
48
|
+
# 验证权限模式
|
|
49
|
+
valid_permission_modes = ["manual", "acceptEdits"]
|
|
50
|
+
if self.permission_mode not in valid_permission_modes:
|
|
51
|
+
raise ValueError(f"无效的权限模式: {self.permission_mode},有效值为: {', '.join(valid_permission_modes)}")
|
|
52
|
+
|
|
53
|
+
# 验证最大对话轮数(-1表示不限制)
|
|
54
|
+
if self.max_turns <= 0 and self.max_turns != -1:
|
|
55
|
+
raise ValueError("max_turns必须为正数或-1(表示不限制)")
|
|
56
|
+
|
|
57
|
+
# 验证会话选项的互斥性
|
|
58
|
+
if self.continue_session and self.resume_session:
|
|
59
|
+
raise ValueError("continue_session和resume_session不能同时设置")
|
|
60
|
+
|
|
61
|
+
# 验证模型参数必须存在
|
|
62
|
+
if not self.model or not self.model.strip():
|
|
63
|
+
raise ValueError("model参数是必需的,请使用 --model 参数指定要使用的模型")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass
|
|
67
|
+
class CLIResult:
|
|
68
|
+
"""CLI执行结果数据类,用于返回命令执行的结果。"""
|
|
69
|
+
|
|
70
|
+
success: bool # 是否成功执行
|
|
71
|
+
output: str = "" # 输出内容
|
|
72
|
+
error: Optional[str] = None # 错误信息
|
|
73
|
+
debug_info: Optional[Dict[str, Any]] = None # 调试信息
|