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,287 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
Auto-Coder SDK 验证工具
|
|
8
|
+
|
|
9
|
+
提供各种数据验证功能。
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import re
|
|
13
|
+
import uuid
|
|
14
|
+
from typing import Any, List, Dict
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from ..models.options import AutoCodeOptions
|
|
18
|
+
from ..exceptions import ValidationError
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def validate_session_id(session_id: str) -> bool:
|
|
22
|
+
"""
|
|
23
|
+
验证会话ID格式
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
session_id: 会话ID
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
bool: 是否有效
|
|
30
|
+
|
|
31
|
+
Raises:
|
|
32
|
+
ValidationError: 验证失败时抛出
|
|
33
|
+
"""
|
|
34
|
+
if not session_id:
|
|
35
|
+
raise ValidationError("session_id", "cannot be empty")
|
|
36
|
+
|
|
37
|
+
# 检查是否为有效的UUID格式
|
|
38
|
+
try:
|
|
39
|
+
uuid.UUID(session_id)
|
|
40
|
+
return True
|
|
41
|
+
except ValueError:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
# 检查是否为有效的自定义格式(字母数字和连字符)
|
|
45
|
+
if re.match(r'^[a-zA-Z0-9\-_]+$', session_id):
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
raise ValidationError(
|
|
49
|
+
"session_id",
|
|
50
|
+
"must be a valid UUID or alphanumeric string with hyphens/underscores"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def validate_options(options: AutoCodeOptions) -> bool:
|
|
55
|
+
"""
|
|
56
|
+
验证AutoCodeOptions对象
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
options: 选项对象
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
bool: 是否有效
|
|
63
|
+
|
|
64
|
+
Raises:
|
|
65
|
+
ValidationError: 验证失败时抛出
|
|
66
|
+
"""
|
|
67
|
+
if not isinstance(options, AutoCodeOptions):
|
|
68
|
+
raise ValidationError("options", "must be an AutoCodeOptions instance")
|
|
69
|
+
|
|
70
|
+
# AutoCodeOptions内部已经有验证,这里调用即可
|
|
71
|
+
options.validate()
|
|
72
|
+
return True
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def validate_file_path(file_path: str, must_exist: bool = False) -> bool:
|
|
76
|
+
"""
|
|
77
|
+
验证文件路径
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
file_path: 文件路径
|
|
81
|
+
must_exist: 是否必须存在
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
bool: 是否有效
|
|
85
|
+
|
|
86
|
+
Raises:
|
|
87
|
+
ValidationError: 验证失败时抛出
|
|
88
|
+
"""
|
|
89
|
+
if not file_path:
|
|
90
|
+
raise ValidationError("file_path", "cannot be empty")
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
path = Path(file_path)
|
|
94
|
+
|
|
95
|
+
if must_exist and not path.exists():
|
|
96
|
+
raise ValidationError("file_path", f"file does not exist: {file_path}")
|
|
97
|
+
|
|
98
|
+
# 检查路径是否合法(不包含非法字符)
|
|
99
|
+
if any(char in str(path) for char in ['<', '>', ':', '"', '|', '?', '*']):
|
|
100
|
+
raise ValidationError("file_path", f"contains invalid characters: {file_path}")
|
|
101
|
+
|
|
102
|
+
return True
|
|
103
|
+
except OSError as e:
|
|
104
|
+
raise ValidationError("file_path", f"invalid path: {str(e)}")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def validate_directory_path(dir_path: str, must_exist: bool = False, create_if_missing: bool = False) -> bool:
|
|
108
|
+
"""
|
|
109
|
+
验证目录路径
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
dir_path: 目录路径
|
|
113
|
+
must_exist: 是否必须存在
|
|
114
|
+
create_if_missing: 如果不存在是否创建
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
bool: 是否有效
|
|
118
|
+
|
|
119
|
+
Raises:
|
|
120
|
+
ValidationError: 验证失败时抛出
|
|
121
|
+
"""
|
|
122
|
+
if not dir_path:
|
|
123
|
+
raise ValidationError("dir_path", "cannot be empty")
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
path = Path(dir_path)
|
|
127
|
+
|
|
128
|
+
if not path.exists():
|
|
129
|
+
if must_exist and not create_if_missing:
|
|
130
|
+
raise ValidationError("dir_path", f"directory does not exist: {dir_path}")
|
|
131
|
+
elif create_if_missing:
|
|
132
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
133
|
+
elif path.exists() and not path.is_dir():
|
|
134
|
+
raise ValidationError("dir_path", f"path exists but is not a directory: {dir_path}")
|
|
135
|
+
|
|
136
|
+
return True
|
|
137
|
+
except OSError as e:
|
|
138
|
+
raise ValidationError("dir_path", f"invalid directory path: {str(e)}")
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def validate_prompt(prompt: str, max_length: int = 10000) -> bool:
|
|
142
|
+
"""
|
|
143
|
+
验证提示内容
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
prompt: 提示内容
|
|
147
|
+
max_length: 最大长度
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
bool: 是否有效
|
|
151
|
+
|
|
152
|
+
Raises:
|
|
153
|
+
ValidationError: 验证失败时抛出
|
|
154
|
+
"""
|
|
155
|
+
if not prompt:
|
|
156
|
+
raise ValidationError("prompt", "cannot be empty")
|
|
157
|
+
|
|
158
|
+
if not isinstance(prompt, str):
|
|
159
|
+
raise ValidationError("prompt", "must be a string")
|
|
160
|
+
|
|
161
|
+
if len(prompt.strip()) == 0:
|
|
162
|
+
raise ValidationError("prompt", "cannot be only whitespace")
|
|
163
|
+
|
|
164
|
+
if len(prompt) > max_length:
|
|
165
|
+
raise ValidationError("prompt", f"exceeds maximum length of {max_length} characters")
|
|
166
|
+
|
|
167
|
+
return True
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def validate_output_format(output_format: str) -> bool:
|
|
171
|
+
"""
|
|
172
|
+
验证输出格式
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
output_format: 输出格式
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
bool: 是否有效
|
|
179
|
+
|
|
180
|
+
Raises:
|
|
181
|
+
ValidationError: 验证失败时抛出
|
|
182
|
+
"""
|
|
183
|
+
from ..constants import OUTPUT_FORMATS
|
|
184
|
+
|
|
185
|
+
if not output_format:
|
|
186
|
+
raise ValidationError("output_format", "cannot be empty")
|
|
187
|
+
|
|
188
|
+
if output_format not in OUTPUT_FORMATS:
|
|
189
|
+
raise ValidationError(
|
|
190
|
+
"output_format",
|
|
191
|
+
f"must be one of: {', '.join(OUTPUT_FORMATS.keys())}"
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
return True
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def validate_permission_mode(permission_mode: str) -> bool:
|
|
198
|
+
"""
|
|
199
|
+
验证权限模式
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
permission_mode: 权限模式
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
bool: 是否有效
|
|
206
|
+
|
|
207
|
+
Raises:
|
|
208
|
+
ValidationError: 验证失败时抛出
|
|
209
|
+
"""
|
|
210
|
+
from ..constants import PERMISSION_MODES
|
|
211
|
+
|
|
212
|
+
if not permission_mode:
|
|
213
|
+
raise ValidationError("permission_mode", "cannot be empty")
|
|
214
|
+
|
|
215
|
+
if permission_mode not in PERMISSION_MODES:
|
|
216
|
+
raise ValidationError(
|
|
217
|
+
"permission_mode",
|
|
218
|
+
f"must be one of: {', '.join(PERMISSION_MODES.keys())}"
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
return True
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def validate_allowed_tools(allowed_tools: List[str]) -> bool:
|
|
225
|
+
"""
|
|
226
|
+
验证允许的工具列表
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
allowed_tools: 工具列表
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
bool: 是否有效
|
|
233
|
+
|
|
234
|
+
Raises:
|
|
235
|
+
ValidationError: 验证失败时抛出
|
|
236
|
+
"""
|
|
237
|
+
from ..constants import ALLOWED_TOOLS
|
|
238
|
+
|
|
239
|
+
if not isinstance(allowed_tools, list):
|
|
240
|
+
raise ValidationError("allowed_tools", "must be a list")
|
|
241
|
+
|
|
242
|
+
if not allowed_tools:
|
|
243
|
+
return True # 空列表表示使用默认工具
|
|
244
|
+
|
|
245
|
+
invalid_tools = set(allowed_tools) - set(ALLOWED_TOOLS)
|
|
246
|
+
if invalid_tools:
|
|
247
|
+
raise ValidationError(
|
|
248
|
+
"allowed_tools",
|
|
249
|
+
f"invalid tools: {', '.join(invalid_tools)}. "
|
|
250
|
+
f"Valid tools: {', '.join(ALLOWED_TOOLS)}"
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
return True
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def validate_metadata(metadata: Dict[str, Any], max_size: int = 1000) -> bool:
|
|
257
|
+
"""
|
|
258
|
+
验证元数据
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
metadata: 元数据字典
|
|
262
|
+
max_size: 最大键值对数量
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
bool: 是否有效
|
|
266
|
+
|
|
267
|
+
Raises:
|
|
268
|
+
ValidationError: 验证失败时抛出
|
|
269
|
+
"""
|
|
270
|
+
if not isinstance(metadata, dict):
|
|
271
|
+
raise ValidationError("metadata", "must be a dictionary")
|
|
272
|
+
|
|
273
|
+
if len(metadata) > max_size:
|
|
274
|
+
raise ValidationError("metadata", f"cannot exceed {max_size} key-value pairs")
|
|
275
|
+
|
|
276
|
+
# 检查键的有效性
|
|
277
|
+
for key in metadata.keys():
|
|
278
|
+
if not isinstance(key, str):
|
|
279
|
+
raise ValidationError("metadata", "all keys must be strings")
|
|
280
|
+
if len(key) > 100:
|
|
281
|
+
raise ValidationError("metadata", f"key '{key}' exceeds maximum length of 100 characters")
|
|
282
|
+
|
|
283
|
+
return True
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
|
autocoder/version.py
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.400"
|
|
2
|
+
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: auto-coder
|
|
3
|
-
Version: 0.1.398
|
|
4
|
-
Summary: AutoCoder: AutoCoder
|
|
5
|
-
Author: allwefantasy
|
|
6
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
7
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
8
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
-
Description-Content-Type: text/markdown
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
Requires-Dist: contextlib2
|
|
12
|
-
Requires-Dist: ninja
|
|
13
|
-
Requires-Dist: jinja2
|
|
14
|
-
Requires-Dist: rich
|
|
15
|
-
Requires-Dist: paramiko
|
|
16
|
-
Requires-Dist: tqdm
|
|
17
|
-
Requires-Dist: loguru
|
|
18
|
-
Requires-Dist: pyjava >=0.6.21
|
|
19
|
-
Requires-Dist: fastapi
|
|
20
|
-
Requires-Dist: uvicorn
|
|
21
|
-
Requires-Dist: retrying
|
|
22
|
-
Requires-Dist: zhipuai
|
|
23
|
-
Requires-Dist: dashscope
|
|
24
|
-
Requires-Dist: tiktoken
|
|
25
|
-
Requires-Dist: tabulate
|
|
26
|
-
Requires-Dist: jupyter-client
|
|
27
|
-
Requires-Dist: prompt-toolkit
|
|
28
|
-
Requires-Dist: tokenizers
|
|
29
|
-
Requires-Dist: aiofiles
|
|
30
|
-
Requires-Dist: readerwriterlock
|
|
31
|
-
Requires-Dist: byzerllm[saas] >=0.1.190
|
|
32
|
-
Requires-Dist: patch
|
|
33
|
-
Requires-Dist: diff-match-patch
|
|
34
|
-
Requires-Dist: GitPython
|
|
35
|
-
Requires-Dist: openai >=1.14.3
|
|
36
|
-
Requires-Dist: anthropic
|
|
37
|
-
Requires-Dist: google-generativeai
|
|
38
|
-
Requires-Dist: protobuf
|
|
39
|
-
Requires-Dist: azure-cognitiveservices-speech
|
|
40
|
-
Requires-Dist: real-agent
|
|
41
|
-
Requires-Dist: duckdb
|
|
42
|
-
Requires-Dist: python-docx
|
|
43
|
-
Requires-Dist: docx2txt
|
|
44
|
-
Requires-Dist: pdf2image
|
|
45
|
-
Requires-Dist: docx2pdf
|
|
46
|
-
Requires-Dist: pypdf
|
|
47
|
-
Requires-Dist: pyperclip
|
|
48
|
-
Requires-Dist: colorama
|
|
49
|
-
Requires-Dist: pylint
|
|
50
|
-
Requires-Dist: reportlab
|
|
51
|
-
Requires-Dist: pathspec
|
|
52
|
-
Requires-Dist: openpyxl
|
|
53
|
-
Requires-Dist: python-pptx
|
|
54
|
-
Requires-Dist: watchfiles
|
|
55
|
-
Requires-Dist: cairosvg
|
|
56
|
-
Requires-Dist: matplotlib
|
|
57
|
-
Requires-Dist: mammoth
|
|
58
|
-
Requires-Dist: markdownify
|
|
59
|
-
Requires-Dist: pdfminer.six
|
|
60
|
-
Requires-Dist: puremagic
|
|
61
|
-
Requires-Dist: pydub
|
|
62
|
-
Requires-Dist: youtube-transcript-api
|
|
63
|
-
Requires-Dist: SpeechRecognition
|
|
64
|
-
Requires-Dist: pathvalidate
|
|
65
|
-
Requires-Dist: pexpect
|
|
66
|
-
Requires-Dist: setuptools
|
|
67
|
-
Requires-Dist: filelock
|
|
68
|
-
Requires-Dist: mcp ; python_version >= "3.10"
|
|
69
|
-
|
|
70
|
-
<p align="center">
|
|
71
|
-
<picture>
|
|
72
|
-
<img alt="auto-coder" src="./logo/auto-coder.jpeg" width=55%>
|
|
73
|
-
</picture>
|
|
74
|
-
</p>
|
|
75
|
-
|
|
76
|
-
<h3 align="center">
|
|
77
|
-
Auto-Coder (powered by Byzer-LLM)
|
|
78
|
-
</h3>
|
|
79
|
-
|
|
80
|
-
<p align="center">
|
|
81
|
-
<a href="https://uelng8wukz.feishu.cn/wiki/QIpkwpQo2iSdkwk9nP6cNSPlnPc"><b>中文</b></a> |
|
|
82
|
-
|
|
83
|
-
</p>
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
*Latest News* 🔥
|
|
88
|
-
- [2025/01] Release Auto-Coder 0.1.208
|
|
89
|
-
- [2024/09] Release Auto-Coder 0.1.163
|
|
90
|
-
- [2024/08] Release Auto-Coder 0.1.143
|
|
91
|
-
- [2024/07] Release Auto-Coder 0.1.115
|
|
92
|
-
- [2024/06] Release Auto-Coder 0.1.82
|
|
93
|
-
- [2024/05] Release Auto-Coder 0.1.73
|
|
94
|
-
- [2024/04] Release Auto-Coder 0.1.46
|
|
95
|
-
- [2024/03] Release Auto-Coder 0.1.25
|
|
96
|
-
- [2024/03] Release Auto-Coder 0.1.24
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
## Installation
|
|
101
|
-
|
|
102
|
-
```shell
|
|
103
|
-
conda create --name autocoder python=3.10.11
|
|
104
|
-
conda activate autocoder
|
|
105
|
-
pip install -U auto-coder
|
|
106
|
-
auto-coder.chat
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Tutorial
|
|
110
|
-
|
|
111
|
-
0. [Auto-Coder.Chat: 通向智能编程之路](https://uelng8wukz.feishu.cn/wiki/QIpkwpQo2iSdkwk9nP6cNSPlnPc)
|
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Compatibility layer for existing conversation implementations.
|
|
3
|
-
|
|
4
|
-
This module provides adapter functions and classes to help
|
|
5
|
-
transition from the existing conversation implementations to
|
|
6
|
-
the new unified conversation manager.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from typing import Dict, List, Any, Optional, Callable, Union
|
|
10
|
-
import time
|
|
11
|
-
from pydantic import BaseModel
|
|
12
|
-
|
|
13
|
-
from autocoder.common import AutoCoderArgs
|
|
14
|
-
from autocoder.common.conversations.conversation_manager import (
|
|
15
|
-
ConversationManager,
|
|
16
|
-
ConversationType,
|
|
17
|
-
get_conversation_manager,
|
|
18
|
-
Message
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# ======= CommandMessage (auto_command.py) Compatibility =======
|
|
23
|
-
|
|
24
|
-
class CommandMessage(BaseModel):
|
|
25
|
-
"""Compatible with auto_command.py CommandMessage."""
|
|
26
|
-
role: str
|
|
27
|
-
content: str
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class ExtendedCommandMessage(BaseModel):
|
|
31
|
-
"""Compatible with auto_command.py ExtendedCommandMessage."""
|
|
32
|
-
message: CommandMessage
|
|
33
|
-
timestamp: str
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class CommandConversation(BaseModel):
|
|
37
|
-
"""Compatible with auto_command.py CommandConversation."""
|
|
38
|
-
history: Dict[str, ExtendedCommandMessage]
|
|
39
|
-
current_conversation: List[ExtendedCommandMessage]
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def command_message_to_message(cmd_msg: Union[CommandMessage, ExtendedCommandMessage]) -> Message:
|
|
43
|
-
"""Convert a CommandMessage or ExtendedCommandMessage to a Message."""
|
|
44
|
-
if isinstance(cmd_msg, ExtendedCommandMessage):
|
|
45
|
-
return Message(
|
|
46
|
-
role=cmd_msg.message.role,
|
|
47
|
-
content=cmd_msg.message.content,
|
|
48
|
-
timestamp=int(cmd_msg.timestamp)
|
|
49
|
-
)
|
|
50
|
-
else:
|
|
51
|
-
return Message(
|
|
52
|
-
role=cmd_msg.role,
|
|
53
|
-
content=cmd_msg.content
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def message_to_command_message(msg: Message) -> ExtendedCommandMessage:
|
|
58
|
-
"""Convert a Message to an ExtendedCommandMessage."""
|
|
59
|
-
return ExtendedCommandMessage(
|
|
60
|
-
message=CommandMessage(
|
|
61
|
-
role=msg.role,
|
|
62
|
-
content=msg.content or ""
|
|
63
|
-
),
|
|
64
|
-
timestamp=str(msg.timestamp or int(time.time()))
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def load_command_conversation(args: AutoCoderArgs, conv_id: str = "command") -> CommandConversation:
|
|
69
|
-
"""
|
|
70
|
-
Load a command conversation in the old format.
|
|
71
|
-
|
|
72
|
-
Args:
|
|
73
|
-
args: AutoCoderArgs object
|
|
74
|
-
conv_id: Conversation ID (defaults to "command")
|
|
75
|
-
|
|
76
|
-
Returns:
|
|
77
|
-
A CommandConversation object compatible with auto_command.py
|
|
78
|
-
"""
|
|
79
|
-
manager = get_conversation_manager(args)
|
|
80
|
-
conversation = manager.get_conversation(
|
|
81
|
-
conv_id=conv_id,
|
|
82
|
-
conv_type=ConversationType.COMMAND,
|
|
83
|
-
create_if_not_exists=True
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
# Convert to old format
|
|
87
|
-
current_conversation = [
|
|
88
|
-
message_to_command_message(msg)
|
|
89
|
-
for msg in conversation.messages
|
|
90
|
-
]
|
|
91
|
-
|
|
92
|
-
# Convert archived conversations
|
|
93
|
-
history = {}
|
|
94
|
-
if conversation.archived_conversations:
|
|
95
|
-
for timestamp, messages in conversation.archived_conversations.items():
|
|
96
|
-
history[timestamp] = [
|
|
97
|
-
message_to_command_message(msg)
|
|
98
|
-
for msg in messages
|
|
99
|
-
]
|
|
100
|
-
|
|
101
|
-
return CommandConversation(
|
|
102
|
-
history=history,
|
|
103
|
-
current_conversation=current_conversation
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def save_command_conversation(
|
|
108
|
-
args: AutoCoderArgs,
|
|
109
|
-
conv: CommandConversation,
|
|
110
|
-
conv_id: str = "command"
|
|
111
|
-
) -> None:
|
|
112
|
-
"""
|
|
113
|
-
Save a command conversation from the old format.
|
|
114
|
-
|
|
115
|
-
Args:
|
|
116
|
-
args: AutoCoderArgs object
|
|
117
|
-
conv: CommandConversation object
|
|
118
|
-
conv_id: Conversation ID (defaults to "command")
|
|
119
|
-
"""
|
|
120
|
-
manager = get_conversation_manager(args)
|
|
121
|
-
conversation = manager.get_conversation(
|
|
122
|
-
conv_id=conv_id,
|
|
123
|
-
conv_type=ConversationType.COMMAND,
|
|
124
|
-
create_if_not_exists=True
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
# Convert messages
|
|
128
|
-
conversation.messages = [
|
|
129
|
-
command_message_to_message(msg)
|
|
130
|
-
for msg in conv.current_conversation
|
|
131
|
-
]
|
|
132
|
-
|
|
133
|
-
# Convert archived conversations
|
|
134
|
-
conversation.archived_conversations = {}
|
|
135
|
-
for timestamp, messages in conv.history.items():
|
|
136
|
-
conversation.archived_conversations[timestamp] = [
|
|
137
|
-
command_message_to_message(msg)
|
|
138
|
-
for msg in messages
|
|
139
|
-
]
|
|
140
|
-
|
|
141
|
-
# Save
|
|
142
|
-
manager._save_conversation(conversation)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def save_to_command_memory_file(
|
|
146
|
-
args: AutoCoderArgs,
|
|
147
|
-
query: str,
|
|
148
|
-
response: str,
|
|
149
|
-
conv_id: str = "command"
|
|
150
|
-
) -> None:
|
|
151
|
-
"""
|
|
152
|
-
Save a command conversation message pair.
|
|
153
|
-
|
|
154
|
-
Args:
|
|
155
|
-
args: AutoCoderArgs object
|
|
156
|
-
query: User query
|
|
157
|
-
response: Assistant response
|
|
158
|
-
conv_id: Conversation ID
|
|
159
|
-
"""
|
|
160
|
-
manager = get_conversation_manager(args)
|
|
161
|
-
conversation = manager.get_conversation(
|
|
162
|
-
conv_id=conv_id,
|
|
163
|
-
conv_type=ConversationType.COMMAND,
|
|
164
|
-
create_if_not_exists=True
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
# Add the messages
|
|
168
|
-
manager.add_user_message(conv_id, query)
|
|
169
|
-
manager.add_assistant_message(conv_id, response)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
# ======= AgenticConversation (agentic_edit_conversation.py) Compatibility =======
|
|
173
|
-
|
|
174
|
-
def get_agentic_conversation(
|
|
175
|
-
args: AutoCoderArgs,
|
|
176
|
-
conversation_name: Optional[str] = None,
|
|
177
|
-
event_id: Optional[str] = None
|
|
178
|
-
) -> 'AgenticConversationWrapper':
|
|
179
|
-
"""
|
|
180
|
-
Get an AgenticConversation wrapper that mimics the original class.
|
|
181
|
-
|
|
182
|
-
Args:
|
|
183
|
-
args: AutoCoderArgs object
|
|
184
|
-
conversation_name: Optional conversation name
|
|
185
|
-
event_id: Optional event ID
|
|
186
|
-
|
|
187
|
-
Returns:
|
|
188
|
-
An AgenticConversationWrapper object compatible with agentic_edit_conversation.py
|
|
189
|
-
"""
|
|
190
|
-
return AgenticConversationWrapper(args, conversation_name, event_id)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
class AgenticConversationWrapper:
|
|
194
|
-
"""Wrapper that mimics the AgenticConversation class from agentic_edit_conversation.py."""
|
|
195
|
-
|
|
196
|
-
def __init__(
|
|
197
|
-
self,
|
|
198
|
-
args: AutoCoderArgs,
|
|
199
|
-
conversation_name: Optional[str] = None,
|
|
200
|
-
event_id: Optional[str] = None,
|
|
201
|
-
initial_history: Optional[List[Dict[str, Any]]] = None
|
|
202
|
-
):
|
|
203
|
-
"""
|
|
204
|
-
Initialize the AgenticConversation wrapper.
|
|
205
|
-
|
|
206
|
-
Args:
|
|
207
|
-
args: AutoCoderArgs object
|
|
208
|
-
conversation_name: Optional conversation name, used as conv_id
|
|
209
|
-
event_id: Optional event ID to associate with this conversation
|
|
210
|
-
initial_history: Optional initial conversation history
|
|
211
|
-
"""
|
|
212
|
-
self.args = args
|
|
213
|
-
self.project_path = args.source_dir
|
|
214
|
-
self.conversation_name = conversation_name or "agentic_edit"
|
|
215
|
-
self.event_id = event_id
|
|
216
|
-
|
|
217
|
-
# Get the conversation manager
|
|
218
|
-
self.manager = get_conversation_manager(args)
|
|
219
|
-
|
|
220
|
-
# Get or create the conversation
|
|
221
|
-
self.conversation = self.manager.get_conversation(
|
|
222
|
-
conv_id=self.conversation_name,
|
|
223
|
-
event_id=self.event_id,
|
|
224
|
-
conv_type=ConversationType.AGENTIC_EDIT,
|
|
225
|
-
create_if_not_exists=True
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
# Add initial history if provided
|
|
229
|
-
if initial_history:
|
|
230
|
-
self._add_initial_history(initial_history)
|
|
231
|
-
|
|
232
|
-
def _add_initial_history(self, history: List[Dict[str, Any]]) -> None:
|
|
233
|
-
"""Add initial history to the conversation."""
|
|
234
|
-
for msg in history:
|
|
235
|
-
role = msg.get("role", "")
|
|
236
|
-
content = msg.get("content", "")
|
|
237
|
-
tool_calls = msg.get("tool_calls", None)
|
|
238
|
-
tool_call_id = msg.get("tool_call_id", None)
|
|
239
|
-
|
|
240
|
-
self.manager.add_message(
|
|
241
|
-
self.conversation.id,
|
|
242
|
-
role,
|
|
243
|
-
content,
|
|
244
|
-
tool_calls=tool_calls,
|
|
245
|
-
tool_call_id=tool_call_id
|
|
246
|
-
)
|
|
247
|
-
|
|
248
|
-
def add_message(self, role: str, content: Any, **kwargs) -> None:
|
|
249
|
-
"""Add a message to the conversation."""
|
|
250
|
-
self.manager.add_message(
|
|
251
|
-
self.conversation.id,
|
|
252
|
-
role,
|
|
253
|
-
content,
|
|
254
|
-
**kwargs
|
|
255
|
-
)
|
|
256
|
-
|
|
257
|
-
def add_user_message(self, content: str) -> None:
|
|
258
|
-
"""Add a user message to the conversation."""
|
|
259
|
-
self.manager.add_user_message(self.conversation.id, content)
|
|
260
|
-
|
|
261
|
-
def add_assistant_message(self, content: str) -> None:
|
|
262
|
-
"""Add an assistant message to the conversation."""
|
|
263
|
-
self.manager.add_assistant_message(self.conversation.id, content)
|
|
264
|
-
|
|
265
|
-
def append_to_last_message(self, content: str, role: str = "assistant") -> None:
|
|
266
|
-
"""Append content to the last message."""
|
|
267
|
-
self.manager.append_to_last_message(
|
|
268
|
-
self.conversation.id,
|
|
269
|
-
content,
|
|
270
|
-
role
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
def add_assistant_tool_call_message(self, tool_calls: List[Dict[str, Any]], content: Optional[str] = None) -> None:
|
|
274
|
-
"""Add a tool call message from the assistant."""
|
|
275
|
-
self.manager.add_tool_call_message(
|
|
276
|
-
self.conversation.id,
|
|
277
|
-
tool_calls,
|
|
278
|
-
content
|
|
279
|
-
)
|
|
280
|
-
|
|
281
|
-
def add_tool_result_message(self, tool_call_id: str, content: Any) -> None:
|
|
282
|
-
"""Add a tool result message."""
|
|
283
|
-
self.manager.add_tool_result_message(
|
|
284
|
-
self.conversation.id,
|
|
285
|
-
tool_call_id,
|
|
286
|
-
content
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
def get_history(self) -> List[Dict[str, Any]]:
|
|
290
|
-
"""Get the conversation history in the format expected by agentic_edit."""
|
|
291
|
-
return self.manager.get_history_as_dict_list(self.conversation.id)
|
|
292
|
-
|
|
293
|
-
def clear_history(self) -> None:
|
|
294
|
-
"""Clear the conversation history."""
|
|
295
|
-
self.manager.clear_conversation(self.conversation.id)
|
|
296
|
-
|
|
297
|
-
def __len__(self) -> int:
|
|
298
|
-
"""Return the number of messages in the conversation."""
|
|
299
|
-
return len(self.conversation.messages)
|
|
300
|
-
|
|
301
|
-
def __str__(self) -> str:
|
|
302
|
-
"""Return a string representation of the conversation."""
|
|
303
|
-
return str(self.get_history())
|